{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating a Deploy App with MONAI Deploy App SDK and MONAI Bundle\n",
    "\n",
    "This tutorial shows how to create an application for organ segmentation using a PyTorch model that has been trained with MONAI and packaged in the [MONAI Bundle](https://docs.monai.io/en/latest/bundle_intro.html) format.\n",
    "\n",
    "Deploying AI models requires the integration with clinical imaging network, even if just in a for-research-use setting. This means that the AI deploy application will need to support standards-based imaging protocols, and specifically for Radiological imaging, DICOM protocol.\n",
    "\n",
    "Typically, DICOM network communication, either in DICOM TCP/IP network protocol or DICOMWeb, would be handled by DICOM devices or services, e.g. MONAI Deploy Informatics Gateway, so the deploy application itself would only need to use DICOM Part 10 files as input and save the AI result in DICOM Part10 file(s). For segmentation use cases, the DICOM instance file for AI results could be a DICOM Segmentation object or a DICOM RT Structure Set, and for classification, DICOM Structure Report and/or DICOM Encapsulated PDF.\n",
    "\n",
    "DICOM instances received from modalities and Picture Archiving and Communications System (PACS) are often times the whole DICOM study, so an AI deploy application has to deal with a whole DICOM study with multiple series, whose images' spacing may not be the same as expected by the trained model. To address these cases consistently and efficiently, MONAI Deploy Application SDK provides classes, called operators, to parse DICOM studies, select specific series with application-defined rules, and convert the selected DICOM series into domain-specific image format along with meta-data representing the pertinent DICOM attributes. The image is then further processed in the pre-processing stage to normalize spacing, orientation, intensity, etc., before pixel data as Tensors are used for inference.\n",
    "\n",
    "In the following sections, we will demonstrate how to create a MONAI Deploy application package using the MONAI Deploy App SDK, and importantly, using the built-in MONAI Bundle Inference Operator to perform inference with the Spleen CT Segmentation PyTorch model in a MONAI Bundle.\n",
    "\n",
    ":::{note}\n",
    "For local testing, if there is a lack of DICOM Part 10 files, one can use open source programs, e.g. 3D Slicer, to convert a NIfTI file to a DICOM series.\n",
    "\n",
    "To make running this example simpler, the DICOM files and the [Spleen CT Segmentation MONAI Bundle](https://github.com/Project-MONAI/model-zoo/tree/dev/models/spleen_ct_segmentation), published in [MONAI Model Zoo](https://github.com/Project-MONAI/model-zoo), have been packaged and shared on Google Drive.\n",
    "\n",
    ":::\n",
    "\n",
    "## Creating Operators and connecting them in Application class\n",
    "\n",
    "We will implement an application that consists of five Operators:\n",
    "\n",
    "- **DICOMDataLoaderOperator**:\n",
    "    - **Input(dicom_files)**: a folder path (`Path`)\n",
    "    - **Output(dicom_study_list)**: a list of DICOM studies in memory (List[[`DICOMStudy`](/modules/_autosummary/monai.deploy.core.domain.DICOMStudy)])\n",
    "- **DICOMSeriesSelectorOperator**:\n",
    "    - **Input(dicom_study_list)**: a list of DICOM studies in memory (List[[`DICOMStudy`](/modules/_autosummary/monai.deploy.core.domain.DICOMStudy)])\n",
    "    - **Input(selection_rules)**: a selection rule (Dict)\n",
    "    - **Output(study_selected_series_list)**: a DICOM series object in memory ([`StudySelectedSeries`](/modules/_autosummary/monai.deploy.core.domain.StudySelectedSeries))\n",
    "- **DICOMSeriesToVolumeOperator**:\n",
    "    - **Input(study_selected_series_list)**: a DICOM series object in memory ([`StudySelectedSeries`](/modules/_autosummary/monai.deploy.core.domain.StudySelectedSeries))\n",
    "    - **Output(image)**: an image object in memory ([`Image`](/modules/_autosummary/monai.deploy.core.domain.Image))\n",
    "- **MonaiBundleInferenceOperator**:\n",
    "    - **Input(image)**: an image object in memory ([`Image`](/modules/_autosummary/monai.deploy.core.domain.Image))\n",
    "    - **Output(pred)**: an image object in memory ([`Image`](/modules/_autosummary/monai.deploy.core.domain.Image))\n",
    "- **DICOMSegmentationWriterOperator**:\n",
    "    - **Input(seg_image)**: a segmentation image object in memory ([`Image`](/modules/_autosummary/monai.deploy.core.domain.Image))\n",
    "    - **Input(study_selected_series_list)**: a DICOM series object in memory ([`StudySelectedSeries`](/modules/_autosummary/monai.deploy.core.domain.StudySelectedSeries))\n",
    "    - **Output(dicom_seg_instance)**: a file path (`Path`)\n",
    "\n",
    "\n",
    ":::{note}\n",
    "The `DICOMSegmentationWriterOperator` needs both the segmentation image as well as the original DICOM series meta-data in order to use the patient demographics and the DICOM Study level attributes.\n",
    ":::\n",
    "\n",
    "The workflow of the application is illustrated below.\n",
    "\n",
    "```{mermaid}\n",
    "%%{init: {\"theme\": \"base\", \"themeVariables\": { \"fontSize\": \"16px\"}} }%%\n",
    "\n",
    "classDiagram\n",
    "    direction TB\n",
    "\n",
    "    DICOMDataLoaderOperator --|> DICOMSeriesSelectorOperator : dicom_study_list...dicom_study_list\n",
    "    DICOMSeriesSelectorOperator --|> DICOMSeriesToVolumeOperator : study_selected_series_list...study_selected_series_list\n",
    "    DICOMSeriesToVolumeOperator --|> MonaiBundleInferenceOperator : image...image\n",
    "    DICOMSeriesSelectorOperator --|> DICOMSegmentationWriterOperator : study_selected_series_list...study_selected_series_list\n",
    "    MonaiBundleInferenceOperator --|> DICOMSegmentationWriterOperator : pred...seg_image\n",
    "\n",
    "\n",
    "    class DICOMDataLoaderOperator {\n",
    "        <in>dicom_files : DISK\n",
    "        dicom_study_list(out) IN_MEMORY\n",
    "    }\n",
    "    class DICOMSeriesSelectorOperator {\n",
    "        <in>dicom_study_list : IN_MEMORY\n",
    "        <in>selection_rules : IN_MEMORY\n",
    "        study_selected_series_list(out) IN_MEMORY\n",
    "    }\n",
    "    class DICOMSeriesToVolumeOperator {\n",
    "        <in>study_selected_series_list : IN_MEMORY\n",
    "        image(out) IN_MEMORY\n",
    "    }\n",
    "    class MonaiBundleInferenceOperator {\n",
    "        <in>image : IN_MEMORY\n",
    "        pred(out) IN_MEMORY\n",
    "    }\n",
    "    class DICOMSegmentationWriterOperator {\n",
    "        <in>seg_image : IN_MEMORY\n",
    "        <in>study_selected_series_list : IN_MEMORY\n",
    "        dicom_seg_instance(out) DISK\n",
    "    }\n",
    "```\n",
    "\n",
    "### Setup environment\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install MONAI and other necessary image processing packages for the application\n",
    "!python -c \"import monai\" || pip install --upgrade -q \"monai\"\n",
    "!python -c \"import torch\" || pip install -q \"torch>=1.12.0\"\n",
    "!python -c \"import numpy\" || pip install -q \"numpy>=1.21.6\"\n",
    "!python -c \"import nibabel\" || pip install -q \"nibabel>=3.2.1\"\n",
    "!python -c \"import pydicom\" || pip install -q \"pydicom>=2.3.0\"\n",
    "!python -c \"import highdicom\" || pip install -q \"highdicom>=0.18.2\"\n",
    "!python -c \"import SimpleITK\" || pip install -q \"SimpleITK>=2.0.0\"\n",
    "!python -c \"import skimage\" || pip install -q \"scikit-image>=0.17.2\"\n",
    "!python -c \"import stl\" || pip install -q \"numpy-stl>=2.12.0\"\n",
    "!python -c \"import trimesh\" || pip install -q \"trimesh>=3.8.11\"\n",
    "\n",
    "# Install MONAI Deploy App SDK package\n",
    "!python -c \"import holoscan\" || pip install --upgrade -q \"holoscan>=0.6.0\"\n",
    "!python -c \"import monai.deploy\" || pip install -q \"monai-deploy-app-sdk\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note: you may need to restart the Jupyter kernel to use the updated packages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Download/Extract input and model/bundle files from Google Drive\n",
    "\n",
    "**_Note:_** Data files are now access controlled. Please first request permission to access the [shared folder on Google Drive](https://drive.google.com/drive/folders/1EONJsrwbGsS30td0hs8zl4WKjihew1Z3?usp=sharing). Please download zip file, `mednist_classifieai_spleen_seg_bundle_data.zip` in the `ai_spleen_seg_app` folder, to the same folder as the notebook example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Archive:  ai_spleen_seg_bundle_data.zip\n",
      "  inflating: dcm/1-001.dcm           \n",
      "  inflating: dcm/1-002.dcm           \n",
      "  inflating: dcm/1-003.dcm           \n",
      "  inflating: dcm/1-004.dcm           \n",
      "  inflating: dcm/1-005.dcm           \n",
      "  inflating: dcm/1-006.dcm           \n",
      "  inflating: dcm/1-007.dcm           \n",
      "  inflating: dcm/1-008.dcm           \n",
      "  inflating: dcm/1-009.dcm           \n",
      "  inflating: dcm/1-010.dcm           \n",
      "  inflating: dcm/1-011.dcm           \n",
      "  inflating: dcm/1-012.dcm           \n",
      "  inflating: dcm/1-013.dcm           \n",
      "  inflating: dcm/1-014.dcm           \n",
      "  inflating: dcm/1-015.dcm           \n",
      "  inflating: dcm/1-016.dcm           \n",
      "  inflating: dcm/1-017.dcm           \n",
      "  inflating: dcm/1-018.dcm           \n",
      "  inflating: dcm/1-019.dcm           \n",
      "  inflating: dcm/1-020.dcm           \n",
      "  inflating: dcm/1-021.dcm           \n",
      "  inflating: dcm/1-022.dcm           \n",
      "  inflating: dcm/1-023.dcm           \n",
      "  inflating: dcm/1-024.dcm           \n",
      "  inflating: dcm/1-025.dcm           \n",
      "  inflating: dcm/1-026.dcm           \n",
      "  inflating: dcm/1-027.dcm           \n",
      "  inflating: dcm/1-028.dcm           \n",
      "  inflating: dcm/1-029.dcm           \n",
      "  inflating: dcm/1-030.dcm           \n",
      "  inflating: dcm/1-031.dcm           \n",
      "  inflating: dcm/1-032.dcm           \n",
      "  inflating: dcm/1-033.dcm           \n",
      "  inflating: dcm/1-034.dcm           \n",
      "  inflating: dcm/1-035.dcm           \n",
      "  inflating: dcm/1-036.dcm           \n",
      "  inflating: dcm/1-037.dcm           \n",
      "  inflating: dcm/1-038.dcm           \n",
      "  inflating: dcm/1-039.dcm           \n",
      "  inflating: dcm/1-040.dcm           \n",
      "  inflating: dcm/1-041.dcm           \n",
      "  inflating: dcm/1-042.dcm           \n",
      "  inflating: dcm/1-043.dcm           \n",
      "  inflating: dcm/1-044.dcm           \n",
      "  inflating: dcm/1-045.dcm           \n",
      "  inflating: dcm/1-046.dcm           \n",
      "  inflating: dcm/1-047.dcm           \n",
      "  inflating: dcm/1-048.dcm           \n",
      "  inflating: dcm/1-049.dcm           \n",
      "  inflating: dcm/1-050.dcm           \n",
      "  inflating: dcm/1-051.dcm           \n",
      "  inflating: dcm/1-052.dcm           \n",
      "  inflating: dcm/1-053.dcm           \n",
      "  inflating: dcm/1-054.dcm           \n",
      "  inflating: dcm/1-055.dcm           \n",
      "  inflating: dcm/1-056.dcm           \n",
      "  inflating: dcm/1-057.dcm           \n",
      "  inflating: dcm/1-058.dcm           \n",
      "  inflating: dcm/1-059.dcm           \n",
      "  inflating: dcm/1-060.dcm           \n",
      "  inflating: dcm/1-061.dcm           \n",
      "  inflating: dcm/1-062.dcm           \n",
      "  inflating: dcm/1-063.dcm           \n",
      "  inflating: dcm/1-064.dcm           \n",
      "  inflating: dcm/1-065.dcm           \n",
      "  inflating: dcm/1-066.dcm           \n",
      "  inflating: dcm/1-067.dcm           \n",
      "  inflating: dcm/1-068.dcm           \n",
      "  inflating: dcm/1-069.dcm           \n",
      "  inflating: dcm/1-070.dcm           \n",
      "  inflating: dcm/1-071.dcm           \n",
      "  inflating: dcm/1-072.dcm           \n",
      "  inflating: dcm/1-073.dcm           \n",
      "  inflating: dcm/1-074.dcm           \n",
      "  inflating: dcm/1-075.dcm           \n",
      "  inflating: dcm/1-076.dcm           \n",
      "  inflating: dcm/1-077.dcm           \n",
      "  inflating: dcm/1-078.dcm           \n",
      "  inflating: dcm/1-079.dcm           \n",
      "  inflating: dcm/1-080.dcm           \n",
      "  inflating: dcm/1-081.dcm           \n",
      "  inflating: dcm/1-082.dcm           \n",
      "  inflating: dcm/1-083.dcm           \n",
      "  inflating: dcm/1-084.dcm           \n",
      "  inflating: dcm/1-085.dcm           \n",
      "  inflating: dcm/1-086.dcm           \n",
      "  inflating: dcm/1-087.dcm           \n",
      "  inflating: dcm/1-088.dcm           \n",
      "  inflating: dcm/1-089.dcm           \n",
      "  inflating: dcm/1-090.dcm           \n",
      "  inflating: dcm/1-091.dcm           \n",
      "  inflating: dcm/1-092.dcm           \n",
      "  inflating: dcm/1-093.dcm           \n",
      "  inflating: dcm/1-094.dcm           \n",
      "  inflating: dcm/1-095.dcm           \n",
      "  inflating: dcm/1-096.dcm           \n",
      "  inflating: dcm/1-097.dcm           \n",
      "  inflating: dcm/1-098.dcm           \n",
      "  inflating: dcm/1-099.dcm           \n",
      "  inflating: dcm/1-100.dcm           \n",
      "  inflating: dcm/1-101.dcm           \n",
      "  inflating: dcm/1-102.dcm           \n",
      "  inflating: dcm/1-103.dcm           \n",
      "  inflating: dcm/1-104.dcm           \n",
      "  inflating: dcm/1-105.dcm           \n",
      "  inflating: dcm/1-106.dcm           \n",
      "  inflating: dcm/1-107.dcm           \n",
      "  inflating: dcm/1-108.dcm           \n",
      "  inflating: dcm/1-109.dcm           \n",
      "  inflating: dcm/1-110.dcm           \n",
      "  inflating: dcm/1-111.dcm           \n",
      "  inflating: dcm/1-112.dcm           \n",
      "  inflating: dcm/1-113.dcm           \n",
      "  inflating: dcm/1-114.dcm           \n",
      "  inflating: dcm/1-115.dcm           \n",
      "  inflating: dcm/1-116.dcm           \n",
      "  inflating: dcm/1-117.dcm           \n",
      "  inflating: dcm/1-118.dcm           \n",
      "  inflating: dcm/1-119.dcm           \n",
      "  inflating: dcm/1-120.dcm           \n",
      "  inflating: dcm/1-121.dcm           \n",
      "  inflating: dcm/1-122.dcm           \n",
      "  inflating: dcm/1-123.dcm           \n",
      "  inflating: dcm/1-124.dcm           \n",
      "  inflating: dcm/1-125.dcm           \n",
      "  inflating: dcm/1-126.dcm           \n",
      "  inflating: dcm/1-127.dcm           \n",
      "  inflating: dcm/1-128.dcm           \n",
      "  inflating: dcm/1-129.dcm           \n",
      "  inflating: dcm/1-130.dcm           \n",
      "  inflating: dcm/1-131.dcm           \n",
      "  inflating: dcm/1-132.dcm           \n",
      "  inflating: dcm/1-133.dcm           \n",
      "  inflating: dcm/1-134.dcm           \n",
      "  inflating: dcm/1-135.dcm           \n",
      "  inflating: dcm/1-136.dcm           \n",
      "  inflating: dcm/1-137.dcm           \n",
      "  inflating: dcm/1-138.dcm           \n",
      "  inflating: dcm/1-139.dcm           \n",
      "  inflating: dcm/1-140.dcm           \n",
      "  inflating: dcm/1-141.dcm           \n",
      "  inflating: dcm/1-142.dcm           \n",
      "  inflating: dcm/1-143.dcm           \n",
      "  inflating: dcm/1-144.dcm           \n",
      "  inflating: dcm/1-145.dcm           \n",
      "  inflating: dcm/1-146.dcm           \n",
      "  inflating: dcm/1-147.dcm           \n",
      "  inflating: dcm/1-148.dcm           \n",
      "  inflating: dcm/1-149.dcm           \n",
      "  inflating: dcm/1-150.dcm           \n",
      "  inflating: dcm/1-151.dcm           \n",
      "  inflating: dcm/1-152.dcm           \n",
      "  inflating: dcm/1-153.dcm           \n",
      "  inflating: dcm/1-154.dcm           \n",
      "  inflating: dcm/1-155.dcm           \n",
      "  inflating: dcm/1-156.dcm           \n",
      "  inflating: dcm/1-157.dcm           \n",
      "  inflating: dcm/1-158.dcm           \n",
      "  inflating: dcm/1-159.dcm           \n",
      "  inflating: dcm/1-160.dcm           \n",
      "  inflating: dcm/1-161.dcm           \n",
      "  inflating: dcm/1-162.dcm           \n",
      "  inflating: dcm/1-163.dcm           \n",
      "  inflating: dcm/1-164.dcm           \n",
      "  inflating: dcm/1-165.dcm           \n",
      "  inflating: dcm/1-166.dcm           \n",
      "  inflating: dcm/1-167.dcm           \n",
      "  inflating: dcm/1-168.dcm           \n",
      "  inflating: dcm/1-169.dcm           \n",
      "  inflating: dcm/1-170.dcm           \n",
      "  inflating: dcm/1-171.dcm           \n",
      "  inflating: dcm/1-172.dcm           \n",
      "  inflating: dcm/1-173.dcm           \n",
      "  inflating: dcm/1-174.dcm           \n",
      "  inflating: dcm/1-175.dcm           \n",
      "  inflating: dcm/1-176.dcm           \n",
      "  inflating: dcm/1-177.dcm           \n",
      "  inflating: dcm/1-178.dcm           \n",
      "  inflating: dcm/1-179.dcm           \n",
      "  inflating: dcm/1-180.dcm           \n",
      "  inflating: dcm/1-181.dcm           \n",
      "  inflating: dcm/1-182.dcm           \n",
      "  inflating: dcm/1-183.dcm           \n",
      "  inflating: dcm/1-184.dcm           \n",
      "  inflating: dcm/1-185.dcm           \n",
      "  inflating: dcm/1-186.dcm           \n",
      "  inflating: dcm/1-187.dcm           \n",
      "  inflating: dcm/1-188.dcm           \n",
      "  inflating: dcm/1-189.dcm           \n",
      "  inflating: dcm/1-190.dcm           \n",
      "  inflating: dcm/1-191.dcm           \n",
      "  inflating: dcm/1-192.dcm           \n",
      "  inflating: dcm/1-193.dcm           \n",
      "  inflating: dcm/1-194.dcm           \n",
      "  inflating: dcm/1-195.dcm           \n",
      "  inflating: dcm/1-196.dcm           \n",
      "  inflating: dcm/1-197.dcm           \n",
      "  inflating: dcm/1-198.dcm           \n",
      "  inflating: dcm/1-199.dcm           \n",
      "  inflating: dcm/1-200.dcm           \n",
      "  inflating: dcm/1-201.dcm           \n",
      "  inflating: dcm/1-202.dcm           \n",
      "  inflating: dcm/1-203.dcm           \n",
      "  inflating: dcm/1-204.dcm           \n",
      "  inflating: model.ts                \n",
      "model.ts\n"
     ]
    }
   ],
   "source": [
    "# Download ai_spleen_bundle_data test data zip file. Please request access and download manually.\n",
    "# !pip install gdown\n",
    "# !gdown \"https://drive.google.com/uc?id=1IwWMpbo2fd38fKIqeIdL8SKTGvkn31tK\"\n",
    "\n",
    "# After downloading ai_spleen_bundle_data zip file from the web browser or using gdown,\n",
    "!unzip -o \"ai_spleen_seg_bundle_data.zip\"\n",
    "\n",
    "# Need to copy the model.ts file to its own clean subfolder for packaging, to workaround an issue in the Packager\n",
    "models_folder = \"models\"\n",
    "!rm -rf {models_folder} && mkdir -p {models_folder}/model && cp model.ts {models_folder}/model && ls {models_folder}/model"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set up environment variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "env: HOLOSCAN_INPUT_PATH=dcm\n",
      "env: HOLOSCAN_MODEL_PATH=models\n",
      "env: HOLOSCAN_OUTPUT_PATH=output\n"
     ]
    }
   ],
   "source": [
    "%env HOLOSCAN_INPUT_PATH dcm\n",
    "%env HOLOSCAN_MODEL_PATH {models_folder}\n",
    "%env HOLOSCAN_OUTPUT_PATH output"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Set up imports\n",
    "\n",
    "Let's import necessary classes/decorators to define Application and Operator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import logging\n",
    "from pathlib import Path\n",
    "\n",
    "# Required for setting SegmentDescription attributes. Direct import as this is not part of App SDK package.\n",
    "from pydicom.sr.codedict import codes\n",
    "\n",
    "from monai.deploy.conditions import CountCondition\n",
    "from monai.deploy.core import AppContext, Application\n",
    "from monai.deploy.core.domain import Image\n",
    "from monai.deploy.core.io_type import IOType\n",
    "from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator\n",
    "from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator, SegmentDescription\n",
    "from monai.deploy.operators.dicom_series_selector_operator import DICOMSeriesSelectorOperator\n",
    "from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator\n",
    "from monai.deploy.operators.monai_bundle_inference_operator import (\n",
    "    BundleConfigNames,\n",
    "    IOMapping,\n",
    "    MonaiBundleInferenceOperator,\n",
    ")\n",
    "from monai.deploy.operators.stl_conversion_operator import STLConversionOperator\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Determining the Input and Output for the Model Bundle Inference Operator\n",
    "\n",
    "The App SDK provides a `MonaiBundleInferenceOperator` class to perform inference with a MONAI Bundle, which is essentially a PyTorch model in TorchScript with additional metadata describing the model network and processing specification. This operator uses the MONAI utilities to parse a MONAI Bundle to automatically instantiate the objects required for input and output processing as well as inference, as such it depends on MONAI transforms, inferers, and in turn their dependencies.\n",
    "\n",
    "Each Operator class inherits from the base `Operator` base class, and its input/output properties are specified in the `setup` function (as opposed to using decorators `@input`and `@output` in Version 0.5 and below).\n",
    "\n",
    "For the `MonaiBundleInferenceOperator` class, the input/output need to be defined to match those of the model network, both in name and data type. For the current release, an `IOMapping` object is used to connect the operator input/output to those of the model network by using the same names. This is likely to change, to be automated, in the future releases once certain limitation in the App SDK is removed.\n",
    "\n",
    "The Spleen CT Segmentation model network has a named input, called \"image\", and the named output called \"pred\", and both are of image type, which can all be mapped to the App SDK [Image](/modules/_autosummary/monai.deploy.core.domain.Image). This piece of information is typically acquired by examining the model metadata `network_data_format` attribute in the bundle, as seen in this [example] (https://github.com/Project-MONAI/model-zoo/blob/dev/models/spleen_ct_segmentation/configs/metadata.json)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating Application class\n",
    "\n",
    "Our application class would look like below.\n",
    "\n",
    "It defines `App` class, inheriting the base `Application` class.\n",
    "\n",
    "Objects required for DICOM parsing, series selection, pixel data conversion to volume image, model specific inference, and the AI result specific DICOM Segmentation object writers are created. The execution pipeline, as a Directed Acyclic Graph, is then constructed by connecting these objects through `self.add_flow()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "class AISpleenSegApp(Application):\n",
    "    \"\"\"Demonstrates inference with built-in MONAI Bundle inference operator with DICOM files as input/output\n",
    "\n",
    "    This application loads a set of DICOM instances, select the appropriate series, converts the series to\n",
    "    3D volume image, performs inference with the built-in MONAI Bundle inference operator, including pre-processing\n",
    "    and post-processing, save the segmentation image in a DICOM Seg OID in an instance file, and optionally the\n",
    "    surface mesh in STL format.\n",
    "\n",
    "    Pertinent MONAI Bundle:\n",
    "      https://github.com/Project-MONAI/model-zoo/tree/dev/models/spleen_ct_segmentation\n",
    "\n",
    "    Execution Time Estimate:\n",
    "      With a Nvidia GV100 32GB GPU, for an input DICOM Series of 515 instances, the execution time is around\n",
    "      25 seconds with saving both DICOM Seg and surface mesh STL file, and 15 seconds with DICOM Seg only.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, *args, **kwargs):\n",
    "        \"\"\"Creates an application instance.\"\"\"\n",
    "        self._logger = logging.getLogger(\"{}.{}\".format(__name__, type(self).__name__))\n",
    "        super().__init__(*args, **kwargs)\n",
    "\n",
    "    def run(self, *args, **kwargs):\n",
    "        # This method calls the base class to run. Can be omitted if simply calling through.\n",
    "        self._logger.info(f\"Begin {self.run.__name__}\")\n",
    "        super().run(*args, **kwargs)\n",
    "        self._logger.info(f\"End {self.run.__name__}\")\n",
    "\n",
    "    def compose(self):\n",
    "        \"\"\"Creates the app specific operators and chain them up in the processing DAG.\"\"\"\n",
    "\n",
    "        logging.info(f\"Begin {self.compose.__name__}\")\n",
    "\n",
    "        app_context = Application.init_app_context({})  # Do not pass argv in Jupyter Notebook\n",
    "        app_input_path = Path(app_context.input_path)\n",
    "        app_output_path = Path(app_context.output_path)\n",
    "        model_path = Path(app_context.model_path)\n",
    "\n",
    "        # Create the custom operator(s) as well as SDK built-in operator(s).\n",
    "        study_loader_op = DICOMDataLoaderOperator(\n",
    "            self, CountCondition(self, 1), input_folder=app_input_path, name=\"study_loader_op\"\n",
    "        )\n",
    "        series_selector_op = DICOMSeriesSelectorOperator(self, rules=Sample_Rules_Text, name=\"series_selector_op\")\n",
    "        series_to_vol_op = DICOMSeriesToVolumeOperator(self, name=\"series_to_vol_op\")\n",
    "\n",
    "        # Create the inference operator that supports MONAI Bundle and automates the inference.\n",
    "        # The IOMapping labels match the input and prediction keys in the pre and post processing.\n",
    "        # The model_name is optional when the app has only one model.\n",
    "        # The bundle_path argument optionally can be set to an accessible bundle file path in the dev\n",
    "        # environment, so when the app is packaged into a MAP, the operator can complete the bundle parsing\n",
    "        # during init.\n",
    "\n",
    "        config_names = BundleConfigNames(config_names=[\"inference\"])  # Same as the default\n",
    "\n",
    "        bundle_spleen_seg_op = MonaiBundleInferenceOperator(\n",
    "            self,\n",
    "            input_mapping=[IOMapping(\"image\", Image, IOType.IN_MEMORY)],\n",
    "            output_mapping=[IOMapping(\"pred\", Image, IOType.IN_MEMORY)],\n",
    "            app_context=app_context,\n",
    "            bundle_config_names=config_names,\n",
    "            bundle_path=model_path,\n",
    "            name=\"bundle_spleen_seg_op\",\n",
    "        )\n",
    "\n",
    "        # Create DICOM Seg writer providing the required segment description for each segment with\n",
    "        # the actual algorithm and the pertinent organ/tissue. The segment_label, algorithm_name,\n",
    "        # and algorithm_version are of DICOM VR LO type, limited to 64 chars.\n",
    "        # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html\n",
    "        segment_descriptions = [\n",
    "            SegmentDescription(\n",
    "                segment_label=\"Spleen\",\n",
    "                segmented_property_category=codes.SCT.Organ,\n",
    "                segmented_property_type=codes.SCT.Spleen,\n",
    "                algorithm_name=\"volumetric (3D) segmentation of the spleen from CT image\",\n",
    "                algorithm_family=codes.DCM.ArtificialIntelligence,\n",
    "                algorithm_version=\"0.3.2\",\n",
    "            )\n",
    "        ]\n",
    "\n",
    "        custom_tags = {\"SeriesDescription\": \"AI generated Seg, not for clinical use.\"}\n",
    "\n",
    "        dicom_seg_writer = DICOMSegmentationWriterOperator(\n",
    "            self,\n",
    "            segment_descriptions=segment_descriptions,\n",
    "            custom_tags=custom_tags,\n",
    "            output_folder=app_output_path,\n",
    "            name=\"dicom_seg_writer\",\n",
    "        )\n",
    "\n",
    "        # Create the processing pipeline, by specifying the source and destination operators, and\n",
    "        # ensuring the output from the former matches the input of the latter, in both name and type.\n",
    "        self.add_flow(study_loader_op, series_selector_op, {(\"dicom_study_list\", \"dicom_study_list\")})\n",
    "        self.add_flow(\n",
    "            series_selector_op, series_to_vol_op, {(\"study_selected_series_list\", \"study_selected_series_list\")}\n",
    "        )\n",
    "        self.add_flow(series_to_vol_op, bundle_spleen_seg_op, {(\"image\", \"image\")})\n",
    "        # Note below the dicom_seg_writer requires two inputs, each coming from a source operator.\n",
    "        self.add_flow(\n",
    "            series_selector_op, dicom_seg_writer, {(\"study_selected_series_list\", \"study_selected_series_list\")}\n",
    "        )\n",
    "        self.add_flow(bundle_spleen_seg_op, dicom_seg_writer, {(\"pred\", \"seg_image\")})\n",
    "        # Create the surface mesh STL conversion operator and add it to the app execution flow, if needed, by\n",
    "        # uncommenting the following couple lines.\n",
    "        stl_conversion_op = STLConversionOperator(\n",
    "            self, output_file=app_output_path.joinpath(\"stl/spleen.stl\"), name=\"stl_conversion_op\"\n",
    "        )\n",
    "        self.add_flow(bundle_spleen_seg_op, stl_conversion_op, {(\"pred\", \"image\")})\n",
    "\n",
    "        logging.info(f\"End {self.compose.__name__}\")\n",
    "\n",
    "\n",
    "# This is a sample series selection rule in JSON, simply selecting CT series.\n",
    "# If the study has more than 1 CT series, then all of them will be selected.\n",
    "# Please see more detail in DICOMSeriesSelectorOperator.\n",
    "Sample_Rules_Text = \"\"\"\n",
    "{\n",
    "    \"selections\": [\n",
    "        {\n",
    "            \"name\": \"CT Series\",\n",
    "            \"conditions\": {\n",
    "                \"StudyDescription\": \"(.*?)\",\n",
    "                \"Modality\": \"(?i)CT\",\n",
    "                \"SeriesDescription\": \"(.*?)\"\n",
    "            }\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Executing app locally\n",
    "\n",
    "We can execute the app in the Jupyter notebook. Note that the DICOM files of the CT Abdomen series must be present in the `dcm` folder and the Torch Script model, `model.ts`, also in the folder as pointed to by the environment variables."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[info] [fragment.cpp:705] Loading extensions from configs...\n",
      "[2025-04-22 10:18:02,158] [INFO] (root) - Parsed args: Namespace(log_level=None, input=None, output=None, model=None, workdir=None, triton_server_netloc=None, argv=[])\n",
      "[2025-04-22 10:18:02,166] [INFO] (root) - AppContext object: AppContext(input_path=dcm, output_path=output, model_path=models, workdir=), triton_server_netloc=\n",
      "[2025-04-22 10:18:02,176] [INFO] (root) - End compose\n",
      "[info] [gxf_executor.cpp:265] Creating context\n",
      "[info] [gxf_executor.cpp:2396] Activating Graph...\n",
      "[info] [gxf_executor.cpp:2426] Running Graph...\n",
      "[info] [gxf_executor.cpp:2428] Waiting for completion...\n",
      "[info] [greedy_scheduler.cpp:191] Scheduling 6 entities\n",
      "[2025-04-22 10:18:02,203] [INFO] (monai.deploy.operators.dicom_data_loader_operator.DICOMDataLoaderOperator) - No or invalid input path from the optional input port: None\n",
      "[2025-04-22 10:18:02,743] [INFO] (root) - Finding series for Selection named: CT Series\n",
      "[2025-04-22 10:18:02,744] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291\n",
      "  # of series: 1\n",
      "[2025-04-22 10:18:02,745] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:02,746] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'\n",
      "[2025-04-22 10:18:02,746] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST\n",
      "[2025-04-22 10:18:02,747] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:02,748] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'\n",
      "[2025-04-22 10:18:02,748] [INFO] (root) -     Series attribute Modality value: CT\n",
      "[2025-04-22 10:18:02,749] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:02,750] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'\n",
      "[2025-04-22 10:18:02,751] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f\n",
      "[2025-04-22 10:18:02,752] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:02,753] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:02,753] [INFO] (root) - Series Selection finalized.\n",
      "[2025-04-22 10:18:02,754] [INFO] (root) - Series Description of selected DICOM Series for inference: ABD/PANC 3.0 B31f\n",
      "[2025-04-22 10:18:02,755] [INFO] (root) - Series Instance UID of selected DICOM Series for inference: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:02,968] [INFO] (root) - Casting to float32\n",
      "[2025-04-22 10:18:03,025] [INFO] (root) - Parsing from bundle_path: /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models/model/model.ts\n",
      "/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.10/site-packages/monai/bundle/reference_resolver.py:216: UserWarning: Detected deprecated name 'optional_packages_version' in configuration file, replacing with 'required_packages_version'.\n",
      "  warnings.warn(\n",
      "[2025-04-22 10:18:06,025] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConversionOperator) - Output will be saved in file output/stl/spleen.stl.\n",
      "[2025-04-22 10:18:07,405] [INFO] (monai.deploy.operators.stl_conversion_operator.SpatialImage) - 3D image\n",
      "[2025-04-22 10:18:07,406] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConverter) - Image ndarray shape:(204, 512, 512)\n",
      "/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.10/site-packages/highdicom/base.py:163: UserWarning: The string \"C3N-00198\" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in https://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.\n",
      "  check_person_name(patient_name)\n",
      "[2025-04-22 10:18:17,835] [INFO] (highdicom.base) - copy Image-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:17,836] [INFO] (highdicom.base) - copy attributes of module \"Specimen\"\n",
      "[2025-04-22 10:18:17,837] [INFO] (highdicom.base) - copy Patient-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:17,838] [INFO] (highdicom.base) - copy attributes of module \"Patient\"\n",
      "[2025-04-22 10:18:17,839] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Subject\"\n",
      "[2025-04-22 10:18:17,839] [INFO] (highdicom.base) - copy Study-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:17,840] [INFO] (highdicom.base) - copy attributes of module \"General Study\"\n",
      "[2025-04-22 10:18:17,841] [INFO] (highdicom.base) - copy attributes of module \"Patient Study\"\n",
      "[2025-04-22 10:18:17,842] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Study\"\n",
      "[info] [greedy_scheduler.cpp:372] Scheduler stopped: Some entities are waiting for execution, but there are no periodic or async entities to get out of the deadlock.\n",
      "[info] [greedy_scheduler.cpp:401] Scheduler finished.\n",
      "[info] [gxf_executor.cpp:2431] Deactivating Graph...\n",
      "[info] [gxf_executor.cpp:2439] Graph execution finished.\n",
      "[2025-04-22 10:18:17,958] [INFO] (__main__.AISpleenSegApp) - End run\n",
      "[2025-04-22 10:18:17,960] [INFO] (root) - End __main__\n"
     ]
    }
   ],
   "source": [
    "!rm -rf $HOLOSCAN_OUTPUT_PATH\n",
    "logging.info(f\"Begin {__name__}\")\n",
    "AISpleenSegApp().run()\n",
    "logging.info(f\"End {__name__}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once the application is verified inside Jupyter notebook, we can write the above Python code into Python files in an application folder.\n",
    "\n",
    "The application folder structure would look like below:\n",
    "\n",
    "```bash\n",
    "my_app\n",
    "├── __main__.py\n",
    "└── app.py\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an application folder\n",
    "!mkdir -p my_app && rm -rf my_app/*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### app.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing my_app/app.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile my_app/app.py\n",
    "\n",
    "# Copyright 2021-2023 MONAI Consortium\n",
    "# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#     http://www.apache.org/licenses/LICENSE-2.0\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License.\n",
    "\n",
    "import logging\n",
    "from pathlib import Path\n",
    "\n",
    "# Required for setting SegmentDescription attributes. Direct import as this is not part of App SDK package.\n",
    "from pydicom.sr.codedict import codes\n",
    "\n",
    "from monai.deploy.conditions import CountCondition\n",
    "from monai.deploy.core import AppContext, Application\n",
    "from monai.deploy.core.domain import Image\n",
    "from monai.deploy.core.io_type import IOType\n",
    "from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator\n",
    "from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator, SegmentDescription\n",
    "from monai.deploy.operators.dicom_series_selector_operator import DICOMSeriesSelectorOperator\n",
    "from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator\n",
    "from monai.deploy.operators.monai_bundle_inference_operator import (\n",
    "    BundleConfigNames,\n",
    "    IOMapping,\n",
    "    MonaiBundleInferenceOperator,\n",
    ")\n",
    "from monai.deploy.operators.stl_conversion_operator import STLConversionOperator\n",
    "\n",
    "\n",
    "class AISpleenSegApp(Application):\n",
    "    \"\"\"Demonstrates inference with built-in MONAI Bundle inference operator with DICOM files as input/output\n",
    "\n",
    "    This application loads a set of DICOM instances, select the appropriate series, converts the series to\n",
    "    3D volume image, performs inference with the built-in MONAI Bundle inference operator, including pre-processing\n",
    "    and post-processing, save the segmentation image in a DICOM Seg OID in an instance file, and optionally the\n",
    "    surface mesh in STL format.\n",
    "\n",
    "    Pertinent MONAI Bundle:\n",
    "      https://github.com/Project-MONAI/model-zoo/tree/dev/models/spleen_ct_segmentation\n",
    "\n",
    "    Execution Time Estimate:\n",
    "      With a Nvidia GV100 32GB GPU, for an input DICOM Series of 515 instances, the execution time is around\n",
    "      25 seconds with saving both DICOM Seg and surface mesh STL file, and 15 seconds with DICOM Seg only.\n",
    "    \"\"\"\n",
    "\n",
    "    def __init__(self, *args, **kwargs):\n",
    "        \"\"\"Creates an application instance.\"\"\"\n",
    "        self._logger = logging.getLogger(\"{}.{}\".format(__name__, type(self).__name__))\n",
    "        super().__init__(*args, **kwargs)\n",
    "\n",
    "    def run(self, *args, **kwargs):\n",
    "        # This method calls the base class to run. Can be omitted if simply calling through.\n",
    "        self._logger.info(f\"Begin {self.run.__name__}\")\n",
    "        super().run(*args, **kwargs)\n",
    "        self._logger.info(f\"End {self.run.__name__}\")\n",
    "\n",
    "    def compose(self):\n",
    "        \"\"\"Creates the app specific operators and chain them up in the processing DAG.\"\"\"\n",
    "\n",
    "        logging.info(f\"Begin {self.compose.__name__}\")\n",
    "\n",
    "        # Use Commandline options over environment variables to init context.\n",
    "        app_context = Application.init_app_context(self.argv)\n",
    "        app_input_path = Path(app_context.input_path)\n",
    "        app_output_path = Path(app_context.output_path)\n",
    "        model_path = Path(app_context.model_path)\n",
    "\n",
    "        # Create the custom operator(s) as well as SDK built-in operator(s).\n",
    "        study_loader_op = DICOMDataLoaderOperator(\n",
    "            self, CountCondition(self, 1), input_folder=app_input_path, name=\"study_loader_op\"\n",
    "        )\n",
    "        series_selector_op = DICOMSeriesSelectorOperator(self, rules=Sample_Rules_Text, name=\"series_selector_op\")\n",
    "        series_to_vol_op = DICOMSeriesToVolumeOperator(self, name=\"series_to_vol_op\")\n",
    "\n",
    "        # Create the inference operator that supports MONAI Bundle and automates the inference.\n",
    "        # The IOMapping labels match the input and prediction keys in the pre and post processing.\n",
    "        # The model_name is optional when the app has only one model.\n",
    "        # The bundle_path argument optionally can be set to an accessible bundle file path in the dev\n",
    "        # environment, so when the app is packaged into a MAP, the operator can complete the bundle parsing\n",
    "        # during init.\n",
    "\n",
    "        config_names = BundleConfigNames(config_names=[\"inference\"])  # Same as the default\n",
    "\n",
    "        bundle_spleen_seg_op = MonaiBundleInferenceOperator(\n",
    "            self,\n",
    "            input_mapping=[IOMapping(\"image\", Image, IOType.IN_MEMORY)],\n",
    "            output_mapping=[IOMapping(\"pred\", Image, IOType.IN_MEMORY)],\n",
    "            app_context=app_context,\n",
    "            bundle_config_names=config_names,\n",
    "            bundle_path=model_path,\n",
    "            name=\"bundle_spleen_seg_op\",\n",
    "        )\n",
    "\n",
    "        # Create DICOM Seg writer providing the required segment description for each segment with\n",
    "        # the actual algorithm and the pertinent organ/tissue. The segment_label, algorithm_name,\n",
    "        # and algorithm_version are of DICOM VR LO type, limited to 64 chars.\n",
    "        # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html\n",
    "        segment_descriptions = [\n",
    "            SegmentDescription(\n",
    "                segment_label=\"Spleen\",\n",
    "                segmented_property_category=codes.SCT.Organ,\n",
    "                segmented_property_type=codes.SCT.Spleen,\n",
    "                algorithm_name=\"volumetric (3D) segmentation of the spleen from CT image\",\n",
    "                algorithm_family=codes.DCM.ArtificialIntelligence,\n",
    "                algorithm_version=\"0.3.2\",\n",
    "            )\n",
    "        ]\n",
    "\n",
    "        custom_tags = {\"SeriesDescription\": \"AI generated Seg, not for clinical use.\"}\n",
    "\n",
    "        dicom_seg_writer = DICOMSegmentationWriterOperator(\n",
    "            self,\n",
    "            segment_descriptions=segment_descriptions,\n",
    "            custom_tags=custom_tags,\n",
    "            output_folder=app_output_path,\n",
    "            name=\"dicom_seg_writer\",\n",
    "        )\n",
    "\n",
    "        # Create the processing pipeline, by specifying the source and destination operators, and\n",
    "        # ensuring the output from the former matches the input of the latter, in both name and type.\n",
    "        self.add_flow(study_loader_op, series_selector_op, {(\"dicom_study_list\", \"dicom_study_list\")})\n",
    "        self.add_flow(\n",
    "            series_selector_op, series_to_vol_op, {(\"study_selected_series_list\", \"study_selected_series_list\")}\n",
    "        )\n",
    "        self.add_flow(series_to_vol_op, bundle_spleen_seg_op, {(\"image\", \"image\")})\n",
    "        # Note below the dicom_seg_writer requires two inputs, each coming from a source operator.\n",
    "        self.add_flow(\n",
    "            series_selector_op, dicom_seg_writer, {(\"study_selected_series_list\", \"study_selected_series_list\")}\n",
    "        )\n",
    "        self.add_flow(bundle_spleen_seg_op, dicom_seg_writer, {(\"pred\", \"seg_image\")})\n",
    "        # Create the surface mesh STL conversion operator and add it to the app execution flow, if needed, by\n",
    "        # uncommenting the following couple lines.\n",
    "        stl_conversion_op = STLConversionOperator(\n",
    "            self, output_file=app_output_path.joinpath(\"stl/spleen.stl\"), name=\"stl_conversion_op\"\n",
    "        )\n",
    "        self.add_flow(bundle_spleen_seg_op, stl_conversion_op, {(\"pred\", \"image\")})\n",
    "\n",
    "        logging.info(f\"End {self.compose.__name__}\")\n",
    "\n",
    "\n",
    "# This is a sample series selection rule in JSON, simply selecting CT series.\n",
    "# If the study has more than 1 CT series, then all of them will be selected.\n",
    "# Please see more detail in DICOMSeriesSelectorOperator.\n",
    "Sample_Rules_Text = \"\"\"\n",
    "{\n",
    "    \"selections\": [\n",
    "        {\n",
    "            \"name\": \"CT Series\",\n",
    "            \"conditions\": {\n",
    "                \"StudyDescription\": \"(.*?)\",\n",
    "                \"Modality\": \"(?i)CT\",\n",
    "                \"SeriesDescription\": \"(.*?)\"\n",
    "            }\n",
    "        }\n",
    "    ]\n",
    "}\n",
    "\"\"\"\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    AISpleenSegApp().run()\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "if __name__ == \"__main__\":\n",
    "    AISpleenSegApp().run()\n",
    "```\n",
    "\n",
    "The above lines are needed to execute the application code by using `python` interpreter.\n",
    "\n",
    "### \\_\\_main\\_\\_.py\n",
    "\n",
    "\\_\\_main\\_\\_.py is needed for <a href=\"../../developing_with_sdk/packaging_app.html#required-arguments\">MONAI Application Packager</a> to detect the main application code (`app.py`) when the application is executed with the application folder path (e.g., `python simple_imaging_app`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing my_app/__main__.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile my_app/__main__.py\n",
    "from app import AISpleenSegApp\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    AISpleenSegApp().run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "app.py\t__main__.py\n"
     ]
    }
   ],
   "source": [
    "!ls my_app"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This time, let's execute the app in the command line.\n",
    "\n",
    ":::{note}\n",
    "Since the environment variables have been set and contain the correct paths, it is not necessary to provide the command line options on running the application. The following command demonstrates the use of the options.\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\u001b[32minfo\u001b[m] [fragment.cpp:705] Loading extensions from configs...\n",
      "[2025-04-22 10:18:22,991] [INFO] (root) - Parsed args: Namespace(log_level=None, input=PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/dcm'), output=PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/output'), model=PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models'), workdir=None, triton_server_netloc=None, argv=['my_app', '-i', 'dcm', '-o', 'output', '-m', 'models'])\n",
      "[2025-04-22 10:18:22,993] [INFO] (root) - AppContext object: AppContext(input_path=/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/dcm, output_path=/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/output, model_path=/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models, workdir=), triton_server_netloc=\n",
      "[2025-04-22 10:18:22,994] [INFO] (root) - End compose\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:265] Creating context\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:2396] Activating Graph...\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:2426] Running Graph...\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:2428] Waiting for completion...\n",
      "[\u001b[32minfo\u001b[m] [greedy_scheduler.cpp:191] Scheduling 6 entities\n",
      "[2025-04-22 10:18:23,011] [INFO] (monai.deploy.operators.dicom_data_loader_operator.DICOMDataLoaderOperator) - No or invalid input path from the optional input port: None\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Finding series for Selection named: CT Series\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291\n",
      "  # of series: 1\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) -     Series attribute Modality value: CT\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f\n",
      "[2025-04-22 10:18:23,326] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "[2025-04-22 10:18:23,327] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:23,327] [INFO] (root) - Series Selection finalized.\n",
      "[2025-04-22 10:18:23,327] [INFO] (root) - Series Description of selected DICOM Series for inference: ABD/PANC 3.0 B31f\n",
      "[2025-04-22 10:18:23,327] [INFO] (root) - Series Instance UID of selected DICOM Series for inference: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "[2025-04-22 10:18:23,535] [INFO] (root) - Casting to float32\n",
      "[2025-04-22 10:18:23,592] [INFO] (root) - Parsing from bundle_path: /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models/model/model.ts\n",
      "/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.10/site-packages/monai/bundle/reference_resolver.py:216: UserWarning: Detected deprecated name 'optional_packages_version' in configuration file, replacing with 'required_packages_version'.\n",
      "  warnings.warn(\n",
      "[2025-04-22 10:18:26,690] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConversionOperator) - Output will be saved in file /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/output/stl/spleen.stl.\n",
      "[2025-04-22 10:18:28,072] [INFO] (monai.deploy.operators.stl_conversion_operator.SpatialImage) - 3D image\n",
      "[2025-04-22 10:18:28,072] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConverter) - Image ndarray shape:(204, 512, 512)\n",
      "/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.10/site-packages/highdicom/base.py:163: UserWarning: The string \"C3N-00198\" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in https://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.\n",
      "  check_person_name(patient_name)\n",
      "[2025-04-22 10:18:38,458] [INFO] (highdicom.base) - copy Image-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:38,458] [INFO] (highdicom.base) - copy attributes of module \"Specimen\"\n",
      "[2025-04-22 10:18:38,458] [INFO] (highdicom.base) - copy Patient-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:38,458] [INFO] (highdicom.base) - copy attributes of module \"Patient\"\n",
      "[2025-04-22 10:18:38,459] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Subject\"\n",
      "[2025-04-22 10:18:38,459] [INFO] (highdicom.base) - copy Study-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "[2025-04-22 10:18:38,459] [INFO] (highdicom.base) - copy attributes of module \"General Study\"\n",
      "[2025-04-22 10:18:38,459] [INFO] (highdicom.base) - copy attributes of module \"Patient Study\"\n",
      "[2025-04-22 10:18:38,459] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Study\"\n",
      "[\u001b[32minfo\u001b[m] [greedy_scheduler.cpp:372] Scheduler stopped: Some entities are waiting for execution, but there are no periodic or async entities to get out of the deadlock.\n",
      "[\u001b[32minfo\u001b[m] [greedy_scheduler.cpp:401] Scheduler finished.\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:2431] Deactivating Graph...\n",
      "[\u001b[32minfo\u001b[m] [gxf_executor.cpp:2439] Graph execution finished.\n",
      "[2025-04-22 10:18:38,554] [INFO] (app.AISpleenSegApp) - End run\n"
     ]
    }
   ],
   "source": [
    "!rm -rf $HOLOSCAN_OUTPUT_PATH\n",
    "!python my_app -i dcm -o output -m models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2.826.0.1.3680043.10.511.3.141985674848102250562862177103472.dcm  stl\n"
     ]
    }
   ],
   "source": [
    "!ls output"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Packaging app\n",
    "\n",
    "Let's package the app with [MONAI Application Packager](/developing_with_sdk/packaging_app).\n",
    "\n",
    "In this version of the App SDK, we need to write out the configuration yaml file as well as the package requirements file, in the application folder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing my_app/app.yaml\n"
     ]
    }
   ],
   "source": [
    "%%writefile my_app/app.yaml\n",
    "%YAML 1.2\n",
    "---\n",
    "application:\n",
    "  title: MONAI Deploy App Package - MONAI Bundle AI App\n",
    "  version: 1.0\n",
    "  inputFormats: [\"file\"]\n",
    "  outputFormats: [\"file\"]\n",
    "\n",
    "resources:\n",
    "  cpu: 1\n",
    "  gpu: 1\n",
    "  memory: 1Gi\n",
    "  gpuMemory: 6Gi"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Writing my_app/requirements.txt\n"
     ]
    }
   ],
   "source": [
    "%%writefile my_app/requirements.txt\n",
    "highdicom>=0.18.2\n",
    "monai>=1.0\n",
    "nibabel>=3.2.1\n",
    "numpy>=1.21.6\n",
    "pydicom>=2.3.0\n",
    "setuptools>=59.5.0 # for pkg_resources\n",
    "SimpleITK>=2.0.0\n",
    "scikit-image>=0.17.2\n",
    "numpy-stl>=2.12.0\n",
    "trimesh>=3.8.11\n",
    "torch>=1.12.0\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we can use the CLI package command to build the MONAI Application Package (MAP) container image based on a supported base image.\n",
    "\n",
    ":::{note}\n",
    "Building a MONAI Application Package (Docker image) can take time. Use `-l DEBUG` option to see the progress.\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2025-04-22 10:18:40,556] [INFO] (common) - Downloading CLI manifest file...\n",
      "[2025-04-22 10:18:40,770] [DEBUG] (common) - Validating CLI manifest file...\n",
      "[2025-04-22 10:18:40,771] [INFO] (packager.parameters) - Application: /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app\n",
      "[2025-04-22 10:18:40,771] [INFO] (packager.parameters) - Detected application type: Python Module\n",
      "[2025-04-22 10:18:40,771] [INFO] (packager) - Scanning for models in /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models...\n",
      "[2025-04-22 10:18:40,772] [DEBUG] (packager) - Model model=/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models/model added.\n",
      "[2025-04-22 10:18:40,772] [INFO] (packager) - Reading application configuration from /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app/app.yaml...\n",
      "[2025-04-22 10:18:40,776] [INFO] (packager) - Generating app.json...\n",
      "[2025-04-22 10:18:40,776] [INFO] (packager) - Generating pkg.json...\n",
      "[2025-04-22 10:18:40,780] [DEBUG] (common) - \n",
      "=============== Begin app.json ===============\n",
      "{\n",
      "    \"apiVersion\": \"1.0.0\",\n",
      "    \"command\": \"[\\\"python3\\\", \\\"/opt/holoscan/app\\\"]\",\n",
      "    \"environment\": {\n",
      "        \"HOLOSCAN_APPLICATION\": \"/opt/holoscan/app\",\n",
      "        \"HOLOSCAN_INPUT_PATH\": \"input/\",\n",
      "        \"HOLOSCAN_OUTPUT_PATH\": \"output/\",\n",
      "        \"HOLOSCAN_WORKDIR\": \"/var/holoscan\",\n",
      "        \"HOLOSCAN_MODEL_PATH\": \"/opt/holoscan/models\",\n",
      "        \"HOLOSCAN_CONFIG_PATH\": \"/var/holoscan/app.yaml\",\n",
      "        \"HOLOSCAN_APP_MANIFEST_PATH\": \"/etc/holoscan/app.json\",\n",
      "        \"HOLOSCAN_PKG_MANIFEST_PATH\": \"/etc/holoscan/pkg.json\",\n",
      "        \"HOLOSCAN_DOCS_PATH\": \"/opt/holoscan/docs\",\n",
      "        \"HOLOSCAN_LOGS_PATH\": \"/var/holoscan/logs\"\n",
      "    },\n",
      "    \"input\": {\n",
      "        \"path\": \"input/\",\n",
      "        \"formats\": null\n",
      "    },\n",
      "    \"liveness\": null,\n",
      "    \"output\": {\n",
      "        \"path\": \"output/\",\n",
      "        \"formats\": null\n",
      "    },\n",
      "    \"readiness\": null,\n",
      "    \"sdk\": \"monai-deploy\",\n",
      "    \"sdkVersion\": \"0.5.1\",\n",
      "    \"timeout\": 0,\n",
      "    \"version\": 1.0,\n",
      "    \"workingDirectory\": \"/var/holoscan\"\n",
      "}\n",
      "================ End app.json ================\n",
      "                 \n",
      "[2025-04-22 10:18:40,781] [DEBUG] (common) - \n",
      "=============== Begin pkg.json ===============\n",
      "{\n",
      "    \"apiVersion\": \"1.0.0\",\n",
      "    \"applicationRoot\": \"/opt/holoscan/app\",\n",
      "    \"modelRoot\": \"/opt/holoscan/models\",\n",
      "    \"models\": {\n",
      "        \"model\": \"/opt/holoscan/models/model\"\n",
      "    },\n",
      "    \"resources\": {\n",
      "        \"cpu\": 1,\n",
      "        \"gpu\": 1,\n",
      "        \"memory\": \"1Gi\",\n",
      "        \"gpuMemory\": \"6Gi\"\n",
      "    },\n",
      "    \"version\": 1.0,\n",
      "    \"platformConfig\": \"dgpu\"\n",
      "}\n",
      "================ End pkg.json ================\n",
      "                 \n",
      "[2025-04-22 10:18:40,804] [DEBUG] (packager.builder) - \n",
      "========== Begin Build Parameters ==========\n",
      "{'additional_lib_paths': '',\n",
      " 'app_config_file_path': PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app/app.yaml'),\n",
      " 'app_dir': PosixPath('/opt/holoscan/app'),\n",
      " 'app_json': '/etc/holoscan/app.json',\n",
      " 'application': PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app'),\n",
      " 'application_directory': PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app'),\n",
      " 'application_type': 'PythonModule',\n",
      " 'build_cache': PosixPath('/home/mqin/.holoscan_build_cache'),\n",
      " 'cmake_args': '',\n",
      " 'command': '[\"python3\", \"/opt/holoscan/app\"]',\n",
      " 'command_filename': 'my_app',\n",
      " 'config_file_path': PosixPath('/var/holoscan/app.yaml'),\n",
      " 'docs_dir': PosixPath('/opt/holoscan/docs'),\n",
      " 'full_input_path': PosixPath('/var/holoscan/input'),\n",
      " 'full_output_path': PosixPath('/var/holoscan/output'),\n",
      " 'gid': 1000,\n",
      " 'holoscan_sdk_version': '3.1.0',\n",
      " 'includes': [],\n",
      " 'input_dir': 'input/',\n",
      " 'lib_dir': PosixPath('/opt/holoscan/lib'),\n",
      " 'logs_dir': PosixPath('/var/holoscan/logs'),\n",
      " 'models': {'model': PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/models/model')},\n",
      " 'models_dir': PosixPath('/opt/holoscan/models'),\n",
      " 'monai_deploy_app_sdk_version': '0.5.1',\n",
      " 'no_cache': False,\n",
      " 'output_dir': 'output/',\n",
      " 'pip_packages': None,\n",
      " 'pkg_json': '/etc/holoscan/pkg.json',\n",
      " 'requirements_file_path': PosixPath('/home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/my_app/requirements.txt'),\n",
      " 'sdk': <SdkType.MonaiDeploy: 'monai-deploy'>,\n",
      " 'sdk_type': 'monai-deploy',\n",
      " 'tarball_output': None,\n",
      " 'timeout': 0,\n",
      " 'title': 'MONAI Deploy App Package - MONAI Bundle AI App',\n",
      " 'uid': 1000,\n",
      " 'username': 'holoscan',\n",
      " 'version': 1.0,\n",
      " 'working_dir': PosixPath('/var/holoscan')}\n",
      "=========== End Build Parameters ===========\n",
      "\n",
      "[2025-04-22 10:18:40,805] [DEBUG] (packager.builder) - \n",
      "========== Begin Platform Parameters ==========\n",
      "{'base_image': 'nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04',\n",
      " 'build_image': None,\n",
      " 'cuda_deb_arch': 'x86_64',\n",
      " 'custom_base_image': False,\n",
      " 'custom_holoscan_sdk': False,\n",
      " 'custom_monai_deploy_sdk': True,\n",
      " 'gpu_type': 'dgpu',\n",
      " 'holoscan_deb_arch': 'amd64',\n",
      " 'holoscan_sdk_file': '3.1.0',\n",
      " 'holoscan_sdk_filename': '3.1.0',\n",
      " 'monai_deploy_sdk_file': PosixPath('/home/mqin/src/monai-deploy-app-sdk/dist/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl'),\n",
      " 'monai_deploy_sdk_filename': 'monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl',\n",
      " 'tag': 'my_app:1.0',\n",
      " 'target_arch': 'x86_64'}\n",
      "=========== End Platform Parameters ===========\n",
      "\n",
      "[2025-04-22 10:18:40,822] [DEBUG] (packager.builder) - \n",
      "========== Begin Dockerfile ==========\n",
      "\n",
      "ARG GPU_TYPE=dgpu\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "FROM nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04 AS base\n",
      "\n",
      "RUN apt-get update \\\n",
      "    && apt-get install -y --no-install-recommends --no-install-suggests \\\n",
      "        curl \\\n",
      "        jq \\\n",
      "    && rm -rf /var/lib/apt/lists/*\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "# FROM base AS mofed-installer\n",
      "# ARG MOFED_VERSION=23.10-2.1.3.1\n",
      "\n",
      "# # In a container, we only need to install the user space libraries, though the drivers are still\n",
      "# # needed on the host.\n",
      "# # Note: MOFED's installation is not easily portable, so we can't copy the output of this stage\n",
      "# # to our final stage, but must inherit from it. For that reason, we keep track of the build/install\n",
      "# # only dependencies in the `MOFED_DEPS` variable (parsing the output of `--check-deps-only`) to\n",
      "# # remove them in that same layer, to ensure they are not propagated in the final image.\n",
      "# WORKDIR /opt/nvidia/mofed\n",
      "# ARG MOFED_INSTALL_FLAGS=\"--dpdk --with-mft --user-space-only --force --without-fw-update\"\n",
      "# RUN UBUNTU_VERSION=$(cat /etc/lsb-release | grep DISTRIB_RELEASE | cut -d= -f2) \\\n",
      "#     && OFED_PACKAGE=\"MLNX_OFED_LINUX-${MOFED_VERSION}-ubuntu${UBUNTU_VERSION}-$(uname -m)\" \\\n",
      "#     && curl -S -# -o ${OFED_PACKAGE}.tgz -L \\\n",
      "#         https://www.mellanox.com/downloads/ofed/MLNX_OFED-${MOFED_VERSION}/${OFED_PACKAGE}.tgz \\\n",
      "#     && tar xf ${OFED_PACKAGE}.tgz \\\n",
      "#     && MOFED_INSTALLER=$(find . -name mlnxofedinstall -type f -executable -print) \\\n",
      "#     && MOFED_DEPS=$(${MOFED_INSTALLER} ${MOFED_INSTALL_FLAGS} --check-deps-only 2>/dev/null | tail -n1 |  cut -d' ' -f3-) \\\n",
      "#     && apt-get update \\\n",
      "#     && apt-get install --no-install-recommends -y ${MOFED_DEPS} \\\n",
      "#     && ${MOFED_INSTALLER} ${MOFED_INSTALL_FLAGS} \\\n",
      "#     && rm -r * \\\n",
      "#     && apt-get remove -y ${MOFED_DEPS} && apt-get autoremove -y \\\n",
      "#     && rm -rf /var/lib/apt/lists/*\n",
      "\n",
      "FROM base AS release\n",
      "ENV DEBIAN_FRONTEND=noninteractive\n",
      "ENV TERM=xterm-256color\n",
      "\n",
      "ARG GPU_TYPE\n",
      "ARG UNAME\n",
      "ARG UID\n",
      "ARG GID\n",
      "\n",
      "RUN mkdir -p /etc/holoscan/ \\\n",
      "        && mkdir -p /opt/holoscan/ \\\n",
      "        && mkdir -p /var/holoscan \\\n",
      "        && mkdir -p /opt/holoscan/app \\\n",
      "        && mkdir -p /var/holoscan/input \\\n",
      "        && mkdir -p /var/holoscan/output\n",
      "\n",
      "LABEL base=\"nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04\"\n",
      "LABEL tag=\"my_app:1.0\"\n",
      "LABEL org.opencontainers.image.title=\"MONAI Deploy App Package - MONAI Bundle AI App\"\n",
      "LABEL org.opencontainers.image.version=\"1.0\"\n",
      "LABEL org.nvidia.holoscan=\"3.1.0\"\n",
      "\n",
      "LABEL org.monai.deploy.app-sdk=\"0.5.1\"\n",
      "\n",
      "ENV HOLOSCAN_INPUT_PATH=/var/holoscan/input\n",
      "ENV HOLOSCAN_OUTPUT_PATH=/var/holoscan/output\n",
      "ENV HOLOSCAN_WORKDIR=/var/holoscan\n",
      "ENV HOLOSCAN_APPLICATION=/opt/holoscan/app\n",
      "ENV HOLOSCAN_TIMEOUT=0\n",
      "ENV HOLOSCAN_MODEL_PATH=/opt/holoscan/models\n",
      "ENV HOLOSCAN_DOCS_PATH=/opt/holoscan/docs\n",
      "ENV HOLOSCAN_CONFIG_PATH=/var/holoscan/app.yaml\n",
      "ENV HOLOSCAN_APP_MANIFEST_PATH=/etc/holoscan/app.json\n",
      "ENV HOLOSCAN_PKG_MANIFEST_PATH=/etc/holoscan/pkg.json\n",
      "ENV HOLOSCAN_LOGS_PATH=/var/holoscan/logs\n",
      "ENV HOLOSCAN_VERSION=3.1.0\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "# If torch is installed, we can skip installing Python\n",
      "ENV PYTHON_VERSION=3.10.6-1~22.04\n",
      "ENV PYTHON_PIP_VERSION=22.0.2+dfsg-*\n",
      "\n",
      "RUN apt update \\\n",
      "    && apt-get install -y --no-install-recommends --no-install-suggests \\\n",
      "        python3-minimal=${PYTHON_VERSION} \\\n",
      "        libpython3-stdlib=${PYTHON_VERSION} \\\n",
      "        python3=${PYTHON_VERSION} \\\n",
      "        python3-venv=${PYTHON_VERSION} \\\n",
      "        python3-pip=${PYTHON_PIP_VERSION} \\\n",
      "    && rm -rf /var/lib/apt/lists/*\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "RUN groupadd -f -g $GID $UNAME\n",
      "RUN useradd -rm -d /home/$UNAME -s /bin/bash -g $GID -G sudo -u $UID $UNAME\n",
      "RUN chown -R holoscan /var/holoscan && \\\n",
      "    chown -R holoscan /var/holoscan/input && \\\n",
      "    chown -R holoscan /var/holoscan/output\n",
      "\n",
      "# Set the working directory\n",
      "WORKDIR /var/holoscan\n",
      "\n",
      "# Copy HAP/MAP tool script\n",
      "COPY ./tools /var/holoscan/tools\n",
      "RUN chmod +x /var/holoscan/tools\n",
      "\n",
      "# Set the working directory\n",
      "WORKDIR /var/holoscan\n",
      "\n",
      "USER $UNAME\n",
      "\n",
      "ENV PATH=/home/${UNAME}/.local/bin:/opt/nvidia/holoscan/bin:$PATH\n",
      "ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/${UNAME}/.local/lib/python3.10/site-packages/holoscan/lib\n",
      "\n",
      "COPY ./pip/requirements.txt /tmp/requirements.txt\n",
      "\n",
      "RUN pip install --upgrade pip\n",
      "RUN pip install --no-cache-dir --user -r /tmp/requirements.txt\n",
      "\n",
      "\n",
      "# Install MONAI Deploy App SDK\n",
      "# Copy user-specified MONAI Deploy SDK file\n",
      "COPY ./monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl /tmp/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "RUN pip install /tmp/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "\n",
      "COPY ./models  /opt/holoscan/models\n",
      "\n",
      "\n",
      "COPY ./map/app.json /etc/holoscan/app.json\n",
      "COPY ./app.config /var/holoscan/app.yaml\n",
      "COPY ./map/pkg.json /etc/holoscan/pkg.json\n",
      "\n",
      "COPY ./app /opt/holoscan/app\n",
      "\n",
      "\n",
      "ENTRYPOINT [\"/var/holoscan/tools\"]\n",
      "=========== End Dockerfile ===========\n",
      "\n",
      "[2025-04-22 10:18:40,822] [INFO] (packager.builder) - \n",
      "===============================================================================\n",
      "Building image for:                 x64-workstation\n",
      "    Architecture:                   linux/amd64\n",
      "    Base Image:                     nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04\n",
      "    Build Image:                    N/A\n",
      "    Cache:                          Enabled\n",
      "    Configuration:                  dgpu\n",
      "    Holoscan SDK Package:           3.1.0\n",
      "    MONAI Deploy App SDK Package:   /home/mqin/src/monai-deploy-app-sdk/dist/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "    gRPC Health Probe:              N/A\n",
      "    SDK Version:                    3.1.0\n",
      "    SDK:                            monai-deploy\n",
      "    Tag:                            my_app-x64-workstation-dgpu-linux-amd64:1.0\n",
      "    Included features/dependencies: N/A\n",
      "    \n",
      "[2025-04-22 10:18:41,210] [INFO] (common) - Using existing Docker BuildKit builder `holoscan_app_builder`\n",
      "[2025-04-22 10:18:41,210] [DEBUG] (packager.builder) - Building Holoscan Application Package: tag=my_app-x64-workstation-dgpu-linux-amd64:1.0\n",
      "#0 building with \"holoscan_app_builder\" instance using docker-container driver\n",
      "\n",
      "#1 [internal] load build definition from Dockerfile\n",
      "#1 transferring dockerfile: 4.74kB done\n",
      "#1 DONE 0.1s\n",
      "\n",
      "#2 [auth] nvidia/cuda:pull token for nvcr.io\n",
      "#2 DONE 0.0s\n",
      "\n",
      "#3 [internal] load metadata for nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04\n",
      "#3 DONE 0.5s\n",
      "\n",
      "#4 [internal] load .dockerignore\n",
      "#4 transferring context: 1.80kB done\n",
      "#4 DONE 0.1s\n",
      "\n",
      "#5 importing cache manifest from local:3932312145486245041\n",
      "#5 inferred cache manifest type: application/vnd.oci.image.index.v1+json done\n",
      "#5 DONE 0.0s\n",
      "\n",
      "#6 [internal] load build context\n",
      "#6 DONE 0.0s\n",
      "\n",
      "#7 [base 1/2] FROM nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04@sha256:22fc009e5cea0b8b91d94c99fdd419d2366810b5ea835e47b8343bc15800c186\n",
      "#7 resolve nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04@sha256:22fc009e5cea0b8b91d94c99fdd419d2366810b5ea835e47b8343bc15800c186 0.0s done\n",
      "#7 DONE 0.0s\n",
      "\n",
      "#8 importing cache manifest from nvcr.io/nvidia/cuda:12.6.0-runtime-ubuntu22.04\n",
      "#8 inferred cache manifest type: application/vnd.docker.distribution.manifest.list.v2+json done\n",
      "#8 DONE 0.3s\n",
      "\n",
      "#6 [internal] load build context\n",
      "#6 transferring context: 19.58MB 0.1s done\n",
      "#6 DONE 0.5s\n",
      "\n",
      "#9 [release  4/19] RUN useradd -rm -d /home/holoscan -s /bin/bash -g 1000 -G sudo -u 1000 holoscan\n",
      "#9 CACHED\n",
      "\n",
      "#10 [release  5/19] RUN chown -R holoscan /var/holoscan &&     chown -R holoscan /var/holoscan/input &&     chown -R holoscan /var/holoscan/output\n",
      "#10 CACHED\n",
      "\n",
      "#11 [release  3/19] RUN groupadd -f -g 1000 holoscan\n",
      "#11 CACHED\n",
      "\n",
      "#12 [release  6/19] WORKDIR /var/holoscan\n",
      "#12 CACHED\n",
      "\n",
      "#13 [release  7/19] COPY ./tools /var/holoscan/tools\n",
      "#13 CACHED\n",
      "\n",
      "#14 [release  8/19] RUN chmod +x /var/holoscan/tools\n",
      "#14 CACHED\n",
      "\n",
      "#15 [release  1/19] RUN mkdir -p /etc/holoscan/         && mkdir -p /opt/holoscan/         && mkdir -p /var/holoscan         && mkdir -p /opt/holoscan/app         && mkdir -p /var/holoscan/input         && mkdir -p /var/holoscan/output\n",
      "#15 CACHED\n",
      "\n",
      "#16 [release  2/19] RUN apt update     && apt-get install -y --no-install-recommends --no-install-suggests         python3-minimal=3.10.6-1~22.04         libpython3-stdlib=3.10.6-1~22.04         python3=3.10.6-1~22.04         python3-venv=3.10.6-1~22.04         python3-pip=22.0.2+dfsg-*     && rm -rf /var/lib/apt/lists/*\n",
      "#16 CACHED\n",
      "\n",
      "#17 [base 2/2] RUN apt-get update     && apt-get install -y --no-install-recommends --no-install-suggests         curl         jq     && rm -rf /var/lib/apt/lists/*\n",
      "#17 CACHED\n",
      "\n",
      "#18 [release  9/19] WORKDIR /var/holoscan\n",
      "#18 CACHED\n",
      "\n",
      "#19 [release 10/19] COPY ./pip/requirements.txt /tmp/requirements.txt\n",
      "#19 DONE 0.2s\n",
      "\n",
      "#20 [release 11/19] RUN pip install --upgrade pip\n",
      "#20 0.826 Defaulting to user installation because normal site-packages is not writeable\n",
      "#20 0.854 Requirement already satisfied: pip in /usr/lib/python3/dist-packages (22.0.2)\n",
      "#20 1.009 Collecting pip\n",
      "#20 1.083   Downloading pip-25.0.1-py3-none-any.whl (1.8 MB)\n",
      "#20 1.257      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 10.9 MB/s eta 0:00:00\n",
      "#20 1.288 Installing collected packages: pip\n",
      "#20 2.028 Successfully installed pip-25.0.1\n",
      "#20 DONE 2.2s\n",
      "\n",
      "#21 [release 12/19] RUN pip install --no-cache-dir --user -r /tmp/requirements.txt\n",
      "#21 0.646 Collecting highdicom>=0.18.2 (from -r /tmp/requirements.txt (line 1))\n",
      "#21 0.682   Downloading highdicom-0.25.1-py3-none-any.whl.metadata (5.0 kB)\n",
      "#21 0.718 Collecting monai>=1.0 (from -r /tmp/requirements.txt (line 2))\n",
      "#21 0.731   Downloading monai-1.4.0-py3-none-any.whl.metadata (11 kB)\n",
      "#21 0.833 Collecting nibabel>=3.2.1 (from -r /tmp/requirements.txt (line 3))\n",
      "#21 0.845   Downloading nibabel-5.3.2-py3-none-any.whl.metadata (9.1 kB)\n",
      "#21 1.074 Collecting numpy>=1.21.6 (from -r /tmp/requirements.txt (line 4))\n",
      "#21 1.085   Downloading numpy-2.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (62 kB)\n",
      "#21 1.122 Collecting pydicom>=2.3.0 (from -r /tmp/requirements.txt (line 5))\n",
      "#21 1.136   Downloading pydicom-3.0.1-py3-none-any.whl.metadata (9.4 kB)\n",
      "#21 1.144 Requirement already satisfied: setuptools>=59.5.0 in /usr/lib/python3/dist-packages (from -r /tmp/requirements.txt (line 6)) (59.6.0)\n",
      "#21 1.183 Collecting SimpleITK>=2.0.0 (from -r /tmp/requirements.txt (line 7))\n",
      "#21 1.193   Downloading SimpleITK-2.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (7.9 kB)\n",
      "#21 1.259 Collecting scikit-image>=0.17.2 (from -r /tmp/requirements.txt (line 8))\n",
      "#21 1.270   Downloading scikit_image-0.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (14 kB)\n",
      "#21 1.303 Collecting numpy-stl>=2.12.0 (from -r /tmp/requirements.txt (line 9))\n",
      "#21 1.315   Downloading numpy_stl-3.2.0-py3-none-any.whl.metadata (18 kB)\n",
      "#21 1.414 Collecting trimesh>=3.8.11 (from -r /tmp/requirements.txt (line 10))\n",
      "#21 1.425   Downloading trimesh-4.6.8-py3-none-any.whl.metadata (18 kB)\n",
      "#21 1.477 Collecting torch>=1.12.0 (from -r /tmp/requirements.txt (line 11))\n",
      "#21 1.488   Downloading torch-2.6.0-cp310-cp310-manylinux1_x86_64.whl.metadata (28 kB)\n",
      "#21 1.650 Collecting pillow>=8.3 (from highdicom>=0.18.2->-r /tmp/requirements.txt (line 1))\n",
      "#21 1.662   Downloading pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl.metadata (8.9 kB)\n",
      "#21 1.711 Collecting pyjpegls>=1.0.0 (from highdicom>=0.18.2->-r /tmp/requirements.txt (line 1))\n",
      "#21 1.724   Downloading pyjpegls-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.5 kB)\n",
      "#21 1.757 Collecting typing-extensions>=4.0.0 (from highdicom>=0.18.2->-r /tmp/requirements.txt (line 1))\n",
      "#21 1.771   Downloading typing_extensions-4.13.2-py3-none-any.whl.metadata (3.0 kB)\n",
      "#21 1.797 Collecting numpy>=1.21.6 (from -r /tmp/requirements.txt (line 4))\n",
      "#21 1.819   Downloading numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\n",
      "#21 1.859 Collecting importlib-resources>=5.12 (from nibabel>=3.2.1->-r /tmp/requirements.txt (line 3))\n",
      "#21 1.871   Downloading importlib_resources-6.5.2-py3-none-any.whl.metadata (3.9 kB)\n",
      "#21 1.923 Collecting packaging>=20 (from nibabel>=3.2.1->-r /tmp/requirements.txt (line 3))\n",
      "#21 1.934   Downloading packaging-25.0-py3-none-any.whl.metadata (3.3 kB)\n",
      "#21 2.041 Collecting scipy>=1.11.4 (from scikit-image>=0.17.2->-r /tmp/requirements.txt (line 8))\n",
      "#21 2.052   Downloading scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\n",
      "#21 2.086 Collecting networkx>=3.0 (from scikit-image>=0.17.2->-r /tmp/requirements.txt (line 8))\n",
      "#21 2.097   Downloading networkx-3.4.2-py3-none-any.whl.metadata (6.3 kB)\n",
      "#21 2.139 Collecting imageio!=2.35.0,>=2.33 (from scikit-image>=0.17.2->-r /tmp/requirements.txt (line 8))\n",
      "#21 2.151   Downloading imageio-2.37.0-py3-none-any.whl.metadata (5.2 kB)\n",
      "#21 2.212 Collecting tifffile>=2022.8.12 (from scikit-image>=0.17.2->-r /tmp/requirements.txt (line 8))\n",
      "#21 2.224   Downloading tifffile-2025.3.30-py3-none-any.whl.metadata (32 kB)\n",
      "#21 2.248 Collecting lazy-loader>=0.4 (from scikit-image>=0.17.2->-r /tmp/requirements.txt (line 8))\n",
      "#21 2.259   Downloading lazy_loader-0.4-py3-none-any.whl.metadata (7.6 kB)\n",
      "#21 2.293 Collecting python-utils>=3.4.5 (from numpy-stl>=2.12.0->-r /tmp/requirements.txt (line 9))\n",
      "#21 2.305   Downloading python_utils-3.9.1-py2.py3-none-any.whl.metadata (9.8 kB)\n",
      "#21 2.367 Collecting filelock (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.378   Downloading filelock-3.18.0-py3-none-any.whl.metadata (2.9 kB)\n",
      "#21 2.412 Collecting jinja2 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.423   Downloading jinja2-3.1.6-py3-none-any.whl.metadata (2.9 kB)\n",
      "#21 2.457 Collecting fsspec (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.468   Downloading fsspec-2025.3.2-py3-none-any.whl.metadata (11 kB)\n",
      "#21 2.550 Collecting nvidia-cuda-nvrtc-cu12==12.4.127 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.561   Downloading nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.581 Collecting nvidia-cuda-runtime-cu12==12.4.127 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.592   Downloading nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.612 Collecting nvidia-cuda-cupti-cu12==12.4.127 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.623   Downloading nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
      "#21 2.642 Collecting nvidia-cudnn-cu12==9.1.0.70 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.653   Downloading nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
      "#21 2.672 Collecting nvidia-cublas-cu12==12.4.5.8 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.683   Downloading nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.702 Collecting nvidia-cufft-cu12==11.2.1.3 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.714   Downloading nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.733 Collecting nvidia-curand-cu12==10.3.5.147 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.743   Downloading nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.762 Collecting nvidia-cusolver-cu12==11.6.1.9 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.773   Downloading nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
      "#21 2.804 Collecting nvidia-cusparse-cu12==12.3.1.170 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.815   Downloading nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)\n",
      "#21 2.831 Collecting nvidia-cusparselt-cu12==0.6.2 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.842   Downloading nvidia_cusparselt_cu12-0.6.2-py3-none-manylinux2014_x86_64.whl.metadata (6.8 kB)\n",
      "#21 2.861 Collecting nvidia-nccl-cu12==2.21.5 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.872   Downloading nvidia_nccl_cu12-2.21.5-py3-none-manylinux2014_x86_64.whl.metadata (1.8 kB)\n",
      "#21 2.895 Collecting nvidia-nvtx-cu12==12.4.127 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.907   Downloading nvidia_nvtx_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.7 kB)\n",
      "#21 2.930 Collecting nvidia-nvjitlink-cu12==12.4.127 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.941   Downloading nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)\n",
      "#21 2.960 Collecting triton==3.2.0 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 2.972   Downloading triton-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (1.4 kB)\n",
      "#21 3.045 Collecting sympy==1.13.1 (from torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 3.055   Downloading sympy-1.13.1-py3-none-any.whl.metadata (12 kB)\n",
      "#21 3.090 Collecting mpmath<1.4,>=1.1.0 (from sympy==1.13.1->torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 3.102   Downloading mpmath-1.3.0-py3-none-any.whl.metadata (8.6 kB)\n",
      "#21 3.144 INFO: pip is looking at multiple versions of pyjpegls to determine which version is compatible with other requirements. This could take a while.\n",
      "#21 3.145 Collecting pyjpegls>=1.0.0 (from highdicom>=0.18.2->-r /tmp/requirements.txt (line 1))\n",
      "#21 3.156   Downloading pyjpegls-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.5 kB)\n",
      "#21 3.170   Downloading pyjpegls-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.5 kB)\n",
      "#21 3.252 Collecting MarkupSafe>=2.0 (from jinja2->torch>=1.12.0->-r /tmp/requirements.txt (line 11))\n",
      "#21 3.263   Downloading MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)\n",
      "#21 3.280 Downloading highdicom-0.25.1-py3-none-any.whl (1.1 MB)\n",
      "#21 3.313    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 51.4 MB/s eta 0:00:00\n",
      "#21 3.328 Downloading monai-1.4.0-py3-none-any.whl (1.5 MB)\n",
      "#21 3.349    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.5/1.5 MB 89.2 MB/s eta 0:00:00\n",
      "#21 3.364 Downloading nibabel-5.3.2-py3-none-any.whl (3.3 MB)\n",
      "#21 3.416    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 MB 67.6 MB/s eta 0:00:00\n",
      "#21 3.431 Downloading numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)\n",
      "#21 3.685    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 18.2/18.2 MB 73.4 MB/s eta 0:00:00\n",
      "#21 3.700 Downloading pydicom-3.0.1-py3-none-any.whl (2.4 MB)\n",
      "#21 3.736    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.4/2.4 MB 75.0 MB/s eta 0:00:00\n",
      "#21 3.751 Downloading SimpleITK-2.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (52.4 MB)\n",
      "#21 4.363    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 52.4/52.4 MB 86.5 MB/s eta 0:00:00\n",
      "#21 4.377 Downloading scikit_image-0.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (14.8 MB)\n",
      "#21 4.533    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.8/14.8 MB 97.9 MB/s eta 0:00:00\n",
      "#21 4.556 Downloading numpy_stl-3.2.0-py3-none-any.whl (20 kB)\n",
      "#21 4.571 Downloading trimesh-4.6.8-py3-none-any.whl (709 kB)\n",
      "#21 4.581    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 709.3/709.3 kB 201.3 MB/s eta 0:00:00\n",
      "#21 4.598 Downloading torch-2.6.0-cp310-cp310-manylinux1_x86_64.whl (766.7 MB)\n",
      "#21 11.67    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 766.7/766.7 MB 106.7 MB/s eta 0:00:00\n",
      "#21 11.69 Downloading nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl (363.4 MB)\n",
      "#21 14.89    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 363.4/363.4 MB 115.9 MB/s eta 0:00:00\n",
      "#21 14.90 Downloading nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (13.8 MB)\n",
      "#21 15.04    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 13.8/13.8 MB 100.5 MB/s eta 0:00:00\n",
      "#21 15.06 Downloading nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (24.6 MB)\n",
      "#21 15.31    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 24.6/24.6 MB 98.3 MB/s eta 0:00:00\n",
      "#21 15.32 Downloading nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (883 kB)\n",
      "#21 15.34    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 883.7/883.7 kB 95.7 MB/s eta 0:00:00\n",
      "#21 15.35 Downloading nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl (664.8 MB)\n",
      "#21 21.33    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 664.8/664.8 MB 109.3 MB/s eta 0:00:00\n",
      "#21 21.34 Downloading nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl (211.5 MB)\n",
      "#21 23.17    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 211.5/211.5 MB 116.0 MB/s eta 0:00:00\n",
      "#21 23.19 Downloading nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl (56.3 MB)\n",
      "#21 23.78    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.3/56.3 MB 95.6 MB/s eta 0:00:00\n",
      "#21 23.80 Downloading nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl (127.9 MB)\n",
      "#21 25.04    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 127.9/127.9 MB 103.4 MB/s eta 0:00:00\n",
      "#21 25.05 Downloading nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl (207.5 MB)\n",
      "#21 26.90    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 207.5/207.5 MB 112.6 MB/s eta 0:00:00\n",
      "#21 26.92 Downloading nvidia_cusparselt_cu12-0.6.2-py3-none-manylinux2014_x86_64.whl (150.1 MB)\n",
      "#21 28.26    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 150.1/150.1 MB 112.3 MB/s eta 0:00:00\n",
      "#21 28.27 Downloading nvidia_nccl_cu12-2.21.5-py3-none-manylinux2014_x86_64.whl (188.7 MB)\n",
      "#21 30.00    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 188.7/188.7 MB 109.4 MB/s eta 0:00:00\n",
      "#21 30.01 Downloading nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (21.1 MB)\n",
      "#21 30.20    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 21.1/21.1 MB 113.9 MB/s eta 0:00:00\n",
      "#21 30.21 Downloading nvidia_nvtx_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (99 kB)\n",
      "#21 30.23 Downloading sympy-1.13.1-py3-none-any.whl (6.2 MB)\n",
      "#21 30.29    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.2/6.2 MB 119.1 MB/s eta 0:00:00\n",
      "#21 30.30 Downloading triton-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (253.1 MB)\n",
      "#21 32.93    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 253.1/253.1 MB 96.3 MB/s eta 0:00:00\n",
      "#21 32.95 Downloading imageio-2.37.0-py3-none-any.whl (315 kB)\n",
      "#21 32.96 Downloading importlib_resources-6.5.2-py3-none-any.whl (37 kB)\n",
      "#21 32.98 Downloading lazy_loader-0.4-py3-none-any.whl (12 kB)\n",
      "#21 32.99 Downloading networkx-3.4.2-py3-none-any.whl (1.7 MB)\n",
      "#21 33.01    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.7/1.7 MB 113.8 MB/s eta 0:00:00\n",
      "#21 33.02 Downloading packaging-25.0-py3-none-any.whl (66 kB)\n",
      "#21 33.04 Downloading pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl (4.6 MB)\n",
      "#21 33.09    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.6/4.6 MB 107.2 MB/s eta 0:00:00\n",
      "#21 33.10 Downloading pyjpegls-1.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB)\n",
      "#21 33.13    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 104.8 MB/s eta 0:00:00\n",
      "#21 33.14 Downloading python_utils-3.9.1-py2.py3-none-any.whl (32 kB)\n",
      "#21 33.15 Downloading scipy-1.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (37.6 MB)\n",
      "#21 33.50    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 37.6/37.6 MB 111.2 MB/s eta 0:00:00\n",
      "#21 33.51 Downloading tifffile-2025.3.30-py3-none-any.whl (226 kB)\n",
      "#21 33.53 Downloading typing_extensions-4.13.2-py3-none-any.whl (45 kB)\n",
      "#21 33.54 Downloading filelock-3.18.0-py3-none-any.whl (16 kB)\n",
      "#21 33.56 Downloading fsspec-2025.3.2-py3-none-any.whl (194 kB)\n",
      "#21 33.57 Downloading jinja2-3.1.6-py3-none-any.whl (134 kB)\n",
      "#21 33.59 Downloading MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (20 kB)\n",
      "#21 33.60 Downloading mpmath-1.3.0-py3-none-any.whl (536 kB)\n",
      "#21 33.61    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 536.2/536.2 kB 201.5 MB/s eta 0:00:00\n",
      "#21 41.09 Installing collected packages: triton, SimpleITK, nvidia-cusparselt-cu12, mpmath, typing-extensions, sympy, pydicom, pillow, packaging, nvidia-nvtx-cu12, nvidia-nvjitlink-cu12, nvidia-nccl-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, nvidia-cublas-cu12, numpy, networkx, MarkupSafe, importlib-resources, fsspec, filelock, trimesh, tifffile, scipy, python-utils, pyjpegls, nvidia-cusparse-cu12, nvidia-cudnn-cu12, nibabel, lazy-loader, jinja2, imageio, scikit-image, nvidia-cusolver-cu12, numpy-stl, highdicom, torch, monai\n",
      "#21 113.8 Successfully installed MarkupSafe-3.0.2 SimpleITK-2.4.1 filelock-3.18.0 fsspec-2025.3.2 highdicom-0.25.1 imageio-2.37.0 importlib-resources-6.5.2 jinja2-3.1.6 lazy-loader-0.4 monai-1.4.0 mpmath-1.3.0 networkx-3.4.2 nibabel-5.3.2 numpy-1.26.4 numpy-stl-3.2.0 nvidia-cublas-cu12-12.4.5.8 nvidia-cuda-cupti-cu12-12.4.127 nvidia-cuda-nvrtc-cu12-12.4.127 nvidia-cuda-runtime-cu12-12.4.127 nvidia-cudnn-cu12-9.1.0.70 nvidia-cufft-cu12-11.2.1.3 nvidia-curand-cu12-10.3.5.147 nvidia-cusolver-cu12-11.6.1.9 nvidia-cusparse-cu12-12.3.1.170 nvidia-cusparselt-cu12-0.6.2 nvidia-nccl-cu12-2.21.5 nvidia-nvjitlink-cu12-12.4.127 nvidia-nvtx-cu12-12.4.127 packaging-25.0 pillow-11.2.1 pydicom-3.0.1 pyjpegls-1.4.0 python-utils-3.9.1 scikit-image-0.25.2 scipy-1.15.2 sympy-1.13.1 tifffile-2025.3.30 torch-2.6.0 trimesh-4.6.8 triton-3.2.0 typing-extensions-4.13.2\n",
      "#21 DONE 117.7s\n",
      "\n",
      "#22 [release 13/19] COPY ./monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl /tmp/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "#22 DONE 0.5s\n",
      "\n",
      "#23 [release 14/19] RUN pip install /tmp/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "#23 0.662 Defaulting to user installation because normal site-packages is not writeable\n",
      "#23 0.785 Processing /tmp/monai_deploy_app_sdk-0.5.1+37.g96f7e31.dirty-py3-none-any.whl\n",
      "#23 0.794 Requirement already satisfied: numpy>=1.21.6 in /home/holoscan/.local/lib/python3.10/site-packages (from monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (1.26.4)\n",
      "#23 0.876 Collecting holoscan~=3.0 (from monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 0.901   Downloading holoscan-3.1.0-cp310-cp310-manylinux_2_35_x86_64.whl.metadata (7.0 kB)\n",
      "#23 0.960 Collecting holoscan-cli~=3.0 (from monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 0.967   Downloading holoscan_cli-3.1.0-py3-none-any.whl.metadata (4.0 kB)\n",
      "#23 1.037 Collecting colorama>=0.4.1 (from monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.043   Downloading colorama-0.4.6-py2.py3-none-any.whl.metadata (17 kB)\n",
      "#23 1.119 Collecting tritonclient>=2.53.0 (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.124   Downloading tritonclient-2.56.0-py3-none-manylinux1_x86_64.whl.metadata (2.8 kB)\n",
      "#23 1.217 Collecting typeguard>=3.0.0 (from monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.222   Downloading typeguard-4.4.2-py3-none-any.whl.metadata (3.8 kB)\n",
      "#23 1.252 Requirement already satisfied: pip>22.0.2 in /home/holoscan/.local/lib/python3.10/site-packages (from holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (25.0.1)\n",
      "#23 1.303 Collecting cupy-cuda12x<14.0,>=12.2 (from holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.308   Downloading cupy_cuda12x-13.4.1-cp310-cp310-manylinux2014_x86_64.whl.metadata (2.6 kB)\n",
      "#23 1.380 Collecting cloudpickle<4.0,>=3.0 (from holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.385   Downloading cloudpickle-3.1.1-py3-none-any.whl.metadata (7.1 kB)\n",
      "#23 1.439 Collecting wheel-axle-runtime<1.0 (from holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.445   Downloading wheel_axle_runtime-0.0.6-py3-none-any.whl.metadata (8.1 kB)\n",
      "#23 1.467 Requirement already satisfied: Jinja2<4.0.0,>=3.1.5 in /home/holoscan/.local/lib/python3.10/site-packages (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (3.1.6)\n",
      "#23 1.515 Collecting packaging<24.0,>=23.1 (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.520   Downloading packaging-23.2-py3-none-any.whl.metadata (3.2 kB)\n",
      "#23 1.646 Collecting psutil<7.0.0,>=6.0.0 (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.650   Downloading psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (22 kB)\n",
      "#23 1.724 Collecting python-on-whales<0.61.0,>=0.60.1 (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.731   Downloading python_on_whales-0.60.1-py3-none-any.whl.metadata (16 kB)\n",
      "#23 1.816 Collecting pyyaml<7.0,>=6.0 (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.820   Downloading PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.1 kB)\n",
      "#23 1.904 Collecting requests<3.0.0,>=2.31.0 (from holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 1.908   Downloading requests-2.32.3-py3-none-any.whl.metadata (4.6 kB)\n",
      "#23 2.039 Collecting python-rapidjson>=0.9.1 (from tritonclient>=2.53.0->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 2.044   Downloading python_rapidjson-1.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (22 kB)\n",
      "#23 2.122 Collecting urllib3>=2.0.7 (from tritonclient>=2.53.0->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 2.126   Downloading urllib3-2.4.0-py3-none-any.whl.metadata (6.5 kB)\n",
      "#23 2.575 Collecting aiohttp<4.0.0,>=3.8.1 (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 2.579   Downloading aiohttp-3.11.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (7.7 kB)\n",
      "#23 2.661 Collecting cuda-python (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 2.665   Downloading cuda_python-12.8.0-py3-none-any.whl.metadata (15 kB)\n",
      "#23 2.815 Collecting geventhttpclient>=2.3.3 (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 2.825   Downloading geventhttpclient-2.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (9.7 kB)\n",
      "#23 3.334 Collecting grpcio<1.68,>=1.63.0 (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.339   Downloading grpcio-1.67.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (3.9 kB)\n",
      "#23 3.555 Collecting protobuf<6.0dev,>=5.26.1 (from tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.559   Downloading protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl.metadata (592 bytes)\n",
      "#23 3.577 Requirement already satisfied: typing_extensions>=4.10.0 in /home/holoscan/.local/lib/python3.10/site-packages (from typeguard>=3.0.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (4.13.2)\n",
      "#23 3.626 Collecting aiohappyeyeballs>=2.3.0 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.632   Downloading aiohappyeyeballs-2.6.1-py3-none-any.whl.metadata (5.9 kB)\n",
      "#23 3.676 Collecting aiosignal>=1.1.2 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.681   Downloading aiosignal-1.3.2-py2.py3-none-any.whl.metadata (3.8 kB)\n",
      "#23 3.748 Collecting async-timeout<6.0,>=4.0 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.753   Downloading async_timeout-5.0.1-py3-none-any.whl.metadata (5.1 kB)\n",
      "#23 3.817 Collecting attrs>=17.3.0 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.823   Downloading attrs-25.3.0-py3-none-any.whl.metadata (10 kB)\n",
      "#23 3.935 Collecting frozenlist>=1.1.1 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 3.940   Downloading frozenlist-1.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (16 kB)\n",
      "#23 4.201 Collecting multidict<7.0,>=4.5 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.205   Downloading multidict-6.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.3 kB)\n",
      "#23 4.297 Collecting propcache>=0.2.0 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.301   Downloading propcache-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (10 kB)\n",
      "#23 4.611 Collecting yarl<2.0,>=1.17.0 (from aiohttp<4.0.0,>=3.8.1->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.615   Downloading yarl-1.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (72 kB)\n",
      "#23 4.699 Collecting fastrlock>=0.5 (from cupy-cuda12x<14.0,>=12.2->holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.704   Downloading fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl.metadata (7.7 kB)\n",
      "#23 4.843 Collecting gevent (from geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.847   Downloading gevent-25.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (13 kB)\n",
      "#23 4.925 Collecting certifi (from geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 4.929   Downloading certifi-2025.1.31-py3-none-any.whl.metadata (2.5 kB)\n",
      "#23 5.003 Collecting brotli (from geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.007   Downloading Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.metadata (5.5 kB)\n",
      "#23 5.027 Requirement already satisfied: MarkupSafe>=2.0 in /home/holoscan/.local/lib/python3.10/site-packages (from Jinja2<4.0.0,>=3.1.5->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (3.0.2)\n",
      "#23 5.170 Collecting pydantic<2,>=1.5 (from python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.175   Downloading pydantic-1.10.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (153 kB)\n",
      "#23 5.306 Collecting tqdm (from python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.310   Downloading tqdm-4.67.1-py3-none-any.whl.metadata (57 kB)\n",
      "#23 5.387 Collecting typer>=0.4.1 (from python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.393   Downloading typer-0.15.2-py3-none-any.whl.metadata (15 kB)\n",
      "#23 5.514 Collecting charset-normalizer<4,>=2 (from requests<3.0.0,>=2.31.0->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.558   Downloading charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (35 kB)\n",
      "#23 5.628 Collecting idna<4,>=2.5 (from requests<3.0.0,>=2.31.0->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.633   Downloading idna-3.10-py3-none-any.whl.metadata (10 kB)\n",
      "#23 5.678 Requirement already satisfied: filelock in /home/holoscan/.local/lib/python3.10/site-packages (from wheel-axle-runtime<1.0->holoscan~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (3.18.0)\n",
      "#23 5.710 Collecting cuda-bindings~=12.8.0 (from cuda-python->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.716   Downloading cuda_bindings-12.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (13 kB)\n",
      "#23 5.807 Collecting click>=8.0.0 (from typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.812   Downloading click-8.1.8-py3-none-any.whl.metadata (2.3 kB)\n",
      "#23 5.872 Collecting shellingham>=1.3.0 (from typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.878   Downloading shellingham-1.5.4-py2.py3-none-any.whl.metadata (3.5 kB)\n",
      "#23 5.971 Collecting rich>=10.11.0 (from typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 5.975   Downloading rich-14.0.0-py3-none-any.whl.metadata (18 kB)\n",
      "#23 6.146 Collecting greenlet>=3.2.0 (from gevent->geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.150   Downloading greenlet-3.2.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.metadata (4.1 kB)\n",
      "#23 6.201 Collecting zope.event (from gevent->geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.208   Downloading zope.event-5.0-py3-none-any.whl.metadata (4.4 kB)\n",
      "#23 6.362 Collecting zope.interface (from gevent->geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.367   Downloading zope.interface-7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (44 kB)\n",
      "#23 6.448 Collecting markdown-it-py>=2.2.0 (from rich>=10.11.0->typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.453   Downloading markdown_it_py-3.0.0-py3-none-any.whl.metadata (6.9 kB)\n",
      "#23 6.524 Collecting pygments<3.0.0,>=2.13.0 (from rich>=10.11.0->typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.529   Downloading pygments-2.19.1-py3-none-any.whl.metadata (2.5 kB)\n",
      "#23 6.548 Requirement already satisfied: setuptools in /usr/lib/python3/dist-packages (from zope.event->gevent->geventhttpclient>=2.3.3->tritonclient[all]>=2.53.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty) (59.6.0)\n",
      "#23 6.591 Collecting mdurl~=0.1 (from markdown-it-py>=2.2.0->rich>=10.11.0->typer>=0.4.1->python-on-whales<0.61.0,>=0.60.1->holoscan-cli~=3.0->monai-deploy-app-sdk==0.5.1+37.g96f7e31.dirty)\n",
      "#23 6.598   Downloading mdurl-0.1.2-py3-none-any.whl.metadata (1.6 kB)\n",
      "#23 6.645 Downloading colorama-0.4.6-py2.py3-none-any.whl (25 kB)\n",
      "#23 6.667 Downloading holoscan-3.1.0-cp310-cp310-manylinux_2_35_x86_64.whl (39.8 MB)\n",
      "#23 8.166    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 39.8/39.8 MB 26.6 MB/s eta 0:00:00\n",
      "#23 8.172 Downloading holoscan_cli-3.1.0-py3-none-any.whl (72 kB)\n",
      "#23 8.194 Downloading tritonclient-2.56.0-py3-none-manylinux1_x86_64.whl (14.4 MB)\n",
      "#23 8.442    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.4/14.4 MB 59.4 MB/s eta 0:00:00\n",
      "#23 8.449 Downloading typeguard-4.4.2-py3-none-any.whl (35 kB)\n",
      "#23 8.477 Downloading aiohttp-3.11.18-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB)\n",
      "#23 8.516    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.6/1.6 MB 39.9 MB/s eta 0:00:00\n",
      "#23 8.522 Downloading cloudpickle-3.1.1-py3-none-any.whl (20 kB)\n",
      "#23 8.545 Downloading cupy_cuda12x-13.4.1-cp310-cp310-manylinux2014_x86_64.whl (104.6 MB)\n",
      "#23 10.10    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 104.6/104.6 MB 67.4 MB/s eta 0:00:00\n",
      "#23 10.11 Downloading geventhttpclient-2.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (112 kB)\n",
      "#23 10.14 Downloading grpcio-1.67.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.9 MB)\n",
      "#23 10.25    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 5.9/5.9 MB 54.0 MB/s eta 0:00:00\n",
      "#23 10.26 Downloading packaging-23.2-py3-none-any.whl (53 kB)\n",
      "#23 10.28 Downloading protobuf-5.29.4-cp38-abi3-manylinux2014_x86_64.whl (319 kB)\n",
      "#23 10.31 Downloading psutil-6.1.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (287 kB)\n",
      "#23 10.34 Downloading python_on_whales-0.60.1-py3-none-any.whl (103 kB)\n",
      "#23 10.36 Downloading python_rapidjson-1.20-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.7 MB)\n",
      "#23 10.41    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.7/1.7 MB 37.3 MB/s eta 0:00:00\n",
      "#23 10.41 Downloading PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (751 kB)\n",
      "#23 10.45    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 751.2/751.2 kB 18.5 MB/s eta 0:00:00\n",
      "#23 10.45 Downloading requests-2.32.3-py3-none-any.whl (64 kB)\n",
      "#23 10.48 Downloading urllib3-2.4.0-py3-none-any.whl (128 kB)\n",
      "#23 10.50 Downloading wheel_axle_runtime-0.0.6-py3-none-any.whl (14 kB)\n",
      "#23 10.53 Downloading cuda_python-12.8.0-py3-none-any.whl (11 kB)\n",
      "#23 10.55 Downloading aiohappyeyeballs-2.6.1-py3-none-any.whl (15 kB)\n",
      "#23 10.57 Downloading aiosignal-1.3.2-py2.py3-none-any.whl (7.6 kB)\n",
      "#23 10.59 Downloading async_timeout-5.0.1-py3-none-any.whl (6.2 kB)\n",
      "#23 10.62 Downloading attrs-25.3.0-py3-none-any.whl (63 kB)\n",
      "#23 10.64 Downloading certifi-2025.1.31-py3-none-any.whl (166 kB)\n",
      "#23 10.67 Downloading charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (146 kB)\n",
      "#23 10.69 Downloading cuda_bindings-12.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.4 MB)\n",
      "#23 10.89    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.4/11.4 MB 59.7 MB/s eta 0:00:00\n",
      "#23 10.90 Downloading fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl (53 kB)\n",
      "#23 10.92 Downloading frozenlist-1.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (287 kB)\n",
      "#23 10.95 Downloading idna-3.10-py3-none-any.whl (70 kB)\n",
      "#23 10.97 Downloading multidict-6.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (219 kB)\n",
      "#23 10.99 Downloading propcache-0.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (206 kB)\n",
      "#23 11.02 Downloading pydantic-1.10.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.3 MB)\n",
      "#23 11.09    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 MB 49.4 MB/s eta 0:00:00\n",
      "#23 11.10 Downloading typer-0.15.2-py3-none-any.whl (45 kB)\n",
      "#23 11.13 Downloading yarl-1.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (333 kB)\n",
      "#23 11.16 Downloading Brotli-1.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (3.0 MB)\n",
      "#23 11.22    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.0/3.0 MB 51.6 MB/s eta 0:00:00\n",
      "#23 11.22 Downloading gevent-25.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.2 MB)\n",
      "#23 11.27    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.2/2.2 MB 44.4 MB/s eta 0:00:00\n",
      "#23 11.28 Downloading tqdm-4.67.1-py3-none-any.whl (78 kB)\n",
      "#23 11.31 Downloading click-8.1.8-py3-none-any.whl (98 kB)\n",
      "#23 11.34 Downloading greenlet-3.2.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (580 kB)\n",
      "#23 11.37    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 580.6/580.6 kB 15.5 MB/s eta 0:00:00\n",
      "#23 11.37 Downloading rich-14.0.0-py3-none-any.whl (243 kB)\n",
      "#23 11.40 Downloading shellingham-1.5.4-py2.py3-none-any.whl (9.8 kB)\n",
      "#23 11.42 Downloading zope.event-5.0-py3-none-any.whl (6.8 kB)\n",
      "#23 11.45 Downloading zope.interface-7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (254 kB)\n",
      "#23 11.47 Downloading markdown_it_py-3.0.0-py3-none-any.whl (87 kB)\n",
      "#23 11.50 Downloading pygments-2.19.1-py3-none-any.whl (1.2 MB)\n",
      "#23 11.54    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 31.5 MB/s eta 0:00:00\n",
      "#23 11.54 Downloading mdurl-0.1.2-py3-none-any.whl (10.0 kB)\n",
      "#23 12.43 Installing collected packages: fastrlock, cuda-bindings, brotli, zope.interface, zope.event, wheel-axle-runtime, urllib3, typeguard, tqdm, shellingham, pyyaml, python-rapidjson, pygments, pydantic, psutil, protobuf, propcache, packaging, multidict, mdurl, idna, grpcio, greenlet, frozenlist, cupy-cuda12x, cuda-python, colorama, cloudpickle, click, charset-normalizer, certifi, attrs, async-timeout, aiohappyeyeballs, yarl, tritonclient, requests, markdown-it-py, holoscan, gevent, aiosignal, rich, geventhttpclient, aiohttp, typer, python-on-whales, holoscan-cli, monai-deploy-app-sdk\n",
      "#23 14.37   Attempting uninstall: packaging\n",
      "#23 14.37     Found existing installation: packaging 25.0\n",
      "#23 14.38     Uninstalling packaging-25.0:\n",
      "#23 14.40       Successfully uninstalled packaging-25.0\n",
      "#23 19.15 Successfully installed aiohappyeyeballs-2.6.1 aiohttp-3.11.18 aiosignal-1.3.2 async-timeout-5.0.1 attrs-25.3.0 brotli-1.1.0 certifi-2025.1.31 charset-normalizer-3.4.1 click-8.1.8 cloudpickle-3.1.1 colorama-0.4.6 cuda-bindings-12.8.0 cuda-python-12.8.0 cupy-cuda12x-13.4.1 fastrlock-0.8.3 frozenlist-1.6.0 gevent-25.4.1 geventhttpclient-2.3.3 greenlet-3.2.1 grpcio-1.67.1 holoscan-3.1.0 holoscan-cli-3.1.0 idna-3.10 markdown-it-py-3.0.0 mdurl-0.1.2 monai-deploy-app-sdk-0.5.1+37.g96f7e31.dirty multidict-6.4.3 packaging-23.2 propcache-0.3.1 protobuf-5.29.4 psutil-6.1.1 pydantic-1.10.21 pygments-2.19.1 python-on-whales-0.60.1 python-rapidjson-1.20 pyyaml-6.0.2 requests-2.32.3 rich-14.0.0 shellingham-1.5.4 tqdm-4.67.1 tritonclient-2.56.0 typeguard-4.4.2 typer-0.15.2 urllib3-2.4.0 wheel-axle-runtime-0.0.6 yarl-1.20.0 zope.event-5.0 zope.interface-7.2\n",
      "#23 DONE 22.0s\n",
      "\n",
      "#24 [release 15/19] COPY ./models  /opt/holoscan/models\n",
      "#24 DONE 0.3s\n",
      "\n",
      "#25 [release 16/19] COPY ./map/app.json /etc/holoscan/app.json\n",
      "#25 DONE 0.1s\n",
      "\n",
      "#26 [release 17/19] COPY ./app.config /var/holoscan/app.yaml\n",
      "#26 DONE 0.1s\n",
      "\n",
      "#27 [release 18/19] COPY ./map/pkg.json /etc/holoscan/pkg.json\n",
      "#27 DONE 0.1s\n",
      "\n",
      "#28 [release 19/19] COPY ./app /opt/holoscan/app\n",
      "#28 DONE 0.1s\n",
      "\n",
      "#29 exporting to docker image format\n",
      "#29 exporting layers\n",
      "#29 exporting layers 187.0s done\n",
      "#29 exporting manifest sha256:cac1ac4d69726995d3c9e061377448492061d466def990799cc72e811e162e90 0.0s done\n",
      "#29 exporting config sha256:aacceda07071b8e9c4e0b360fd0b819d987eef71230c11c95f76c3053bfbd861 0.0s done\n",
      "#29 sending tarball\n",
      "#29 ...\n",
      "\n",
      "#30 importing to docker\n",
      "#30 loading layer 49b545b4149c 283B / 283B\n",
      "#30 loading layer c44b5ca75fdc 65.54kB / 5.09MB\n",
      "#30 loading layer 3370fbb67e83 557.06kB / 3.26GB\n",
      "#30 loading layer 3370fbb67e83 210.01MB / 3.26GB 6.3s\n",
      "#30 loading layer 3370fbb67e83 337.02MB / 3.26GB 12.5s\n",
      "#30 loading layer 3370fbb67e83 550.37MB / 3.26GB 18.7s\n",
      "#30 loading layer 3370fbb67e83 735.31MB / 3.26GB 22.8s\n",
      "#30 loading layer 3370fbb67e83 963.15MB / 3.26GB 27.0s\n",
      "#30 loading layer 3370fbb67e83 1.18GB / 3.26GB 31.0s\n",
      "#30 loading layer 3370fbb67e83 1.33GB / 3.26GB 37.2s\n",
      "#30 loading layer 3370fbb67e83 1.56GB / 3.26GB 41.3s\n",
      "#30 loading layer 3370fbb67e83 1.75GB / 3.26GB 45.4s\n",
      "#30 loading layer 3370fbb67e83 2.02GB / 3.26GB 49.4s\n",
      "#30 loading layer 3370fbb67e83 2.19GB / 3.26GB 55.6s\n",
      "#30 loading layer 3370fbb67e83 2.24GB / 3.26GB 62.9s\n",
      "#30 loading layer 3370fbb67e83 2.36GB / 3.26GB 69.0s\n",
      "#30 loading layer 3370fbb67e83 2.56GB / 3.26GB 73.1s\n",
      "#30 loading layer 3370fbb67e83 2.75GB / 3.26GB 77.1s\n",
      "#30 loading layer 3370fbb67e83 2.93GB / 3.26GB 83.3s\n",
      "#30 loading layer 3370fbb67e83 3.10GB / 3.26GB 89.5s\n",
      "#30 loading layer af8c5ba7bee3 32.77kB / 144.30kB\n",
      "#30 loading layer 8f8123670c0a 557.06kB / 398.53MB\n",
      "#30 loading layer 8f8123670c0a 197.20MB / 398.53MB 2.1s\n",
      "#30 loading layer 8f8123670c0a 228.95MB / 398.53MB 4.1s\n",
      "#30 loading layer 8f8123670c0a 270.73MB / 398.53MB 6.2s\n",
      "#30 loading layer 8f8123670c0a 334.23MB / 398.53MB 8.2s\n",
      "#30 loading layer 8f8123670c0a 368.21MB / 398.53MB 10.3s\n",
      "#30 loading layer c277737c154f 196.61kB / 17.81MB\n",
      "#30 loading layer 01f35eabeadd 493B / 493B\n",
      "#30 loading layer 21a6f7132dd0 316B / 316B\n",
      "#30 loading layer 22aecd36f9de 302B / 302B\n",
      "#30 loading layer ab9d985fcc93 3.33kB / 3.33kB\n",
      "#30 loading layer 8f8123670c0a 398.53MB / 398.53MB 13.6s done\n",
      "#30 loading layer 49b545b4149c 283B / 283B 109.9s done\n",
      "#30 loading layer c44b5ca75fdc 5.09MB / 5.09MB 109.9s done\n",
      "#30 loading layer 3370fbb67e83 3.26GB / 3.26GB 109.2s done\n",
      "#30 loading layer af8c5ba7bee3 144.30kB / 144.30kB 13.7s done\n",
      "#30 loading layer c277737c154f 17.81MB / 17.81MB 1.1s done\n",
      "#30 loading layer 01f35eabeadd 493B / 493B 0.7s done\n",
      "#30 loading layer 21a6f7132dd0 316B / 316B 0.6s done\n",
      "#30 loading layer 22aecd36f9de 302B / 302B 0.5s done\n",
      "#30 loading layer ab9d985fcc93 3.33kB / 3.33kB 0.5s done\n",
      "#30 DONE 109.9s\n",
      "\n",
      "#29 exporting to docker image format\n",
      "#29 sending tarball 147.3s done\n",
      "#29 DONE 334.4s\n",
      "\n",
      "#31 exporting cache to client directory\n",
      "#31 preparing build cache for export\n",
      "#31 writing layer sha256:000344a04deee760c0681e29294ee3f527b8299026aef2cfc3fa93e327c63df7\n",
      "#31 writing layer sha256:000344a04deee760c0681e29294ee3f527b8299026aef2cfc3fa93e327c63df7 0.1s done\n",
      "#31 writing layer sha256:048e6a80d9e1847dcc9526191c8d16c8bdda32e8440cb0e287ba48983787b2ea 0.0s done\n",
      "#31 writing layer sha256:1a0d52c93099897b518eb6cc6cd0fa3d52ff733e8606b4d8c92675ba9e7101ff done\n",
      "#31 writing layer sha256:21ef12df128643f4e171d286035dc9c1a1e744f0ff52681473844fa3ebf148f9\n",
      "#31 writing layer sha256:21ef12df128643f4e171d286035dc9c1a1e744f0ff52681473844fa3ebf148f9 51.1s done\n",
      "#31 writing layer sha256:234b866f57e0c5d555af2d87a1857a17ec4ac7e70d2dc6c31ff0a072a4607f24\n",
      "#31 writing layer sha256:234b866f57e0c5d555af2d87a1857a17ec4ac7e70d2dc6c31ff0a072a4607f24 done\n",
      "#31 writing layer sha256:255905badeaa82f032e1043580eed8b745c19cd4a2cb7183883ee5a30f851d6d done\n",
      "#31 writing layer sha256:3713021b02770a720dea9b54c03d0ed83e03a2ef5dce2898c56a327fee9a8bca done\n",
      "#31 writing layer sha256:3a80776cdc9c9ef79bb38510849c9160f82462d346bf5a8bf29c811391b4e763 done\n",
      "#31 writing layer sha256:46c9c54348df10b0d7700bf932d5de7dc5bf9ab91e685db7086e29e381ff8e12 done\n",
      "#31 writing layer sha256:4984bf91ddd07bd551024b1b6bda153f7d4f5a5caf35d9e2ca01c95afb531638 0.0s done\n",
      "#31 writing layer sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 done\n",
      "#31 writing layer sha256:67b3546b211deefd67122e680c0932886e0b3c6bd6ae0665e3ab25d2d9f0cda0 done\n",
      "#31 writing layer sha256:76cf1f2adf6fbbaa3d9ff2c120fc0ccf97b4b5388ee0a0dee82f894ea811caf8 0.1s done\n",
      "#31 writing layer sha256:8a18a20487f64bf7fe1ac7ead38280d387b11f3d714179e19b4ecfba68a09f93\n",
      "#31 writing layer sha256:8a18a20487f64bf7fe1ac7ead38280d387b11f3d714179e19b4ecfba68a09f93 0.0s done\n",
      "#31 writing layer sha256:935b4cb3480886ca00a46c28cd98797870cfc7389818c85cd243869f4548fda4 done\n",
      "#31 writing layer sha256:95dbda2f5f8116a35367b28d397faae7d34bd4a713aefe01ccfe5e326b0b0250 done\n",
      "#31 writing layer sha256:980c13e156f90218b216bc6b0430472bbda71c0202804d350c0e16ef02075885 done\n",
      "#31 writing layer sha256:9897f28322ebd7b633908503d8877b342e03a47293fcacdc8206b2e5d9f20923\n",
      "#31 writing layer sha256:9897f28322ebd7b633908503d8877b342e03a47293fcacdc8206b2e5d9f20923 0.4s done\n",
      "#31 writing layer sha256:ac52600be001236a2c291a4c5902c915bf5ec9d2441c06d2a54c587b76345847\n",
      "#31 writing layer sha256:ac52600be001236a2c291a4c5902c915bf5ec9d2441c06d2a54c587b76345847 done\n",
      "#31 writing layer sha256:b0436fe850f9a3fce99cc083d570eb3393b83444edf2dc04800a8e4d050d2d83 0.0s done\n",
      "#31 writing layer sha256:bc25d810fc1fd99656c1b07d422e88cdb896508730175bc3ec187b79f3787044 done\n",
      "#31 writing layer sha256:d0b9db5eaf93e490f07bab8abb1ac5475febcf822c25f2e1d1c82ff4273a7d0d done\n",
      "#31 writing layer sha256:d339273dfb7fc3b7fd896d3610d360ab9a09ab33a818093cb73b4be7639b6e99 done\n",
      "#31 writing layer sha256:da44fb0aa6d6f7c651c7eec8e11510c9c048b066b2ba36b261cefea12ff5ee3e done\n",
      "#31 writing layer sha256:efc9014e2a4cb1e133b80bb4f047e9141e98685eb95b8d2471a8e35b86643e31 done\n",
      "#31 writing layer sha256:f1e6c0e7271e4ce12dd1113858066e0d41d50b338596aea2c15a21da034a7d3d 0.0s done\n",
      "#31 writing layer sha256:f3af93a430a247328c59fb2228f6fa43a0ce742b03464db94acf7c45311e31cd done\n",
      "#31 writing layer sha256:ff7fc9bdba2b206dc4eb678f49b36a99daf566bf71753dc2cec30a0195f7a41a\n",
      "#31 writing layer sha256:ff7fc9bdba2b206dc4eb678f49b36a99daf566bf71753dc2cec30a0195f7a41a 6.8s done\n",
      "#31 preparing build cache for export 58.8s done\n",
      "#31 writing config sha256:1401476261a3e0a96b4b64a3270960c3fa51a70d62e0cd7a30991c3da24af97e 0.0s done\n",
      "#31 writing cache manifest sha256:b4e7496beec087df8709332743a34f2f69a9993f4fdf0ac0d1871c03d8664448 0.0s done\n",
      "#31 DONE 58.8s\n",
      "[2025-04-22 10:27:40,090] [INFO] (packager) - Build Summary:\n",
      "\n",
      "Platform: x64-workstation/dgpu\n",
      "    Status:     Succeeded\n",
      "    Docker Tag: my_app-x64-workstation-dgpu-linux-amd64:1.0\n",
      "    Tarball:    None\n"
     ]
    }
   ],
   "source": [
    "tag_prefix = \"my_app\"\n",
    "\n",
    "!monai-deploy package my_app -m {models_folder} -c my_app/app.yaml -t {tag_prefix}:1.0 --platform x86_64 -l DEBUG"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see that the MAP Docker image is created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "my_app-x64-workstation-dgpu-linux-amd64                                       1.0                            aacceda07071   6 minutes ago    9.25GB\n"
     ]
    }
   ],
   "source": [
    "!docker image ls | grep {tag_prefix}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can choose to display and inspect the MAP manifests by running the container with the `show` command.\n",
    "Furthermore, we can also extract the manifests and other contents in the MAP by using the `extract` command while mapping specific folder to the host's (we know that our MAP is compliant and supports these commands).\n",
    "\n",
    ":::{note}\n",
    "The host folder for storing the extracted content must first be created by the user, and if it has been created by Docker on running the container, the folder needs to be deleted and re-created.\n",
    ":::"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Display manifests and extract MAP contents to the host folder, ./export\n",
      "\n",
      "============================== app.json ==============================\n",
      "{\n",
      "  \"apiVersion\": \"1.0.0\",\n",
      "  \"command\": \"[\\\"python3\\\", \\\"/opt/holoscan/app\\\"]\",\n",
      "  \"environment\": {\n",
      "    \"HOLOSCAN_APPLICATION\": \"/opt/holoscan/app\",\n",
      "    \"HOLOSCAN_INPUT_PATH\": \"input/\",\n",
      "    \"HOLOSCAN_OUTPUT_PATH\": \"output/\",\n",
      "    \"HOLOSCAN_WORKDIR\": \"/var/holoscan\",\n",
      "    \"HOLOSCAN_MODEL_PATH\": \"/opt/holoscan/models\",\n",
      "    \"HOLOSCAN_CONFIG_PATH\": \"/var/holoscan/app.yaml\",\n",
      "    \"HOLOSCAN_APP_MANIFEST_PATH\": \"/etc/holoscan/app.json\",\n",
      "    \"HOLOSCAN_PKG_MANIFEST_PATH\": \"/etc/holoscan/pkg.json\",\n",
      "    \"HOLOSCAN_DOCS_PATH\": \"/opt/holoscan/docs\",\n",
      "    \"HOLOSCAN_LOGS_PATH\": \"/var/holoscan/logs\"\n",
      "  },\n",
      "  \"input\": {\n",
      "    \"path\": \"input/\",\n",
      "    \"formats\": null\n",
      "  },\n",
      "  \"liveness\": null,\n",
      "  \"output\": {\n",
      "    \"path\": \"output/\",\n",
      "    \"formats\": null\n",
      "  },\n",
      "  \"readiness\": null,\n",
      "  \"sdk\": \"monai-deploy\",\n",
      "  \"sdkVersion\": \"0.5.1\",\n",
      "  \"timeout\": 0,\n",
      "  \"version\": 1,\n",
      "  \"workingDirectory\": \"/var/holoscan\"\n",
      "}\n",
      "\n",
      "============================== pkg.json ==============================\n",
      "{\n",
      "  \"apiVersion\": \"1.0.0\",\n",
      "  \"applicationRoot\": \"/opt/holoscan/app\",\n",
      "  \"modelRoot\": \"/opt/holoscan/models\",\n",
      "  \"models\": {\n",
      "    \"model\": \"/opt/holoscan/models/model\"\n",
      "  },\n",
      "  \"resources\": {\n",
      "    \"cpu\": 1,\n",
      "    \"gpu\": 1,\n",
      "    \"memory\": \"1Gi\",\n",
      "    \"gpuMemory\": \"6Gi\"\n",
      "  },\n",
      "  \"version\": 1,\n",
      "  \"platformConfig\": \"dgpu\"\n",
      "}\n",
      "\n",
      "2025-04-22 17:27:43 [INFO] Copying application from /opt/holoscan/app to /var/run/holoscan/export/app\n",
      "\n",
      "2025-04-22 17:27:43 [INFO] Copying application manifest file from /etc/holoscan/app.json to /var/run/holoscan/export/config/app.json\n",
      "2025-04-22 17:27:43 [INFO] Copying pkg manifest file from /etc/holoscan/pkg.json to /var/run/holoscan/export/config/pkg.json\n",
      "2025-04-22 17:27:43 [INFO] Copying application configuration from /var/holoscan/app.yaml to /var/run/holoscan/export/config/app.yaml\n",
      "\n",
      "2025-04-22 17:27:43 [INFO] Copying models from /opt/holoscan/models to /var/run/holoscan/export/models\n",
      "\n",
      "2025-04-22 17:27:43 [INFO] Copying documentation from /opt/holoscan/docs/ to /var/run/holoscan/export/docs\n",
      "2025-04-22 17:27:43 [INFO] '/opt/holoscan/docs/' cannot be found.\n",
      "\n",
      "app  config  models\n"
     ]
    }
   ],
   "source": [
    "!echo \"Display manifests and extract MAP contents to the host folder, ./export\"\n",
    "!docker run --rm {tag_prefix}-x64-workstation-dgpu-linux-amd64:1.0 show\n",
    "!rm -rf `pwd`/export && mkdir -p `pwd`/export\n",
    "!docker run --rm -v `pwd`/export/:/var/run/holoscan/export/ {tag_prefix}-x64-workstation-dgpu-linux-amd64:1.0 extract\n",
    "!ls `pwd`/export"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Executing packaged app locally\n",
    "\n",
    "The packaged app can be run locally through [MONAI Application Runner](/developing_with_sdk/executing_packaged_app_locally)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2025-04-22 10:27:44,899] [INFO] (runner) - Checking dependencies...\n",
      "[2025-04-22 10:27:44,899] [INFO] (runner) - --> Verifying if \"docker\" is installed...\n",
      "\n",
      "[2025-04-22 10:27:44,899] [INFO] (runner) - --> Verifying if \"docker-buildx\" is installed...\n",
      "\n",
      "[2025-04-22 10:27:44,900] [INFO] (runner) - --> Verifying if \"my_app-x64-workstation-dgpu-linux-amd64:1.0\" is available...\n",
      "\n",
      "[2025-04-22 10:27:44,977] [INFO] (runner) - Reading HAP/MAP manifest...\n",
      "Successfully copied 2.56kB to /tmp/tmpmnebv7ra/app.json\n",
      "Successfully copied 2.05kB to /tmp/tmpmnebv7ra/pkg.json\n",
      "bb0cf20f8662e86bcda22ed7a5faae90e0b66cdd38d6f64a8e2ceb4e95a0ebca\n",
      "[2025-04-22 10:27:45,406] [INFO] (runner) - --> Verifying if \"nvidia-ctk\" is installed...\n",
      "\n",
      "[2025-04-22 10:27:45,407] [INFO] (runner) - --> Verifying \"nvidia-ctk\" version...\n",
      "\n",
      "[2025-04-22 10:27:45,714] [INFO] (common) - Launching container (21c6001bf0ef) using image 'my_app-x64-workstation-dgpu-linux-amd64:1.0'...\n",
      "    container name:      youthful_jepsen\n",
      "    host name:           mingq-dt\n",
      "    network:             host\n",
      "    user:                1000:1000\n",
      "    ulimits:             memlock=-1:-1, stack=67108864:67108864\n",
      "    cap_add:             CAP_SYS_PTRACE\n",
      "    ipc mode:            host\n",
      "    shared memory size:  67108864\n",
      "    devices:             \n",
      "    group_add:           44\n",
      "2025-04-22 17:27:46 [INFO] Launching application python3 /opt/holoscan/app ...\n",
      "\n",
      "[info] [fragment.cpp:705] Loading extensions from configs...\n",
      "\n",
      "[info] [gxf_executor.cpp:265] Creating context\n",
      "\n",
      "[2025-04-22 17:27:53,854] [INFO] (root) - Parsed args: Namespace(log_level=None, input=None, output=None, model=None, workdir=None, triton_server_netloc=None, argv=['/opt/holoscan/app'])\n",
      "\n",
      "[2025-04-22 17:27:53,858] [INFO] (root) - AppContext object: AppContext(input_path=/var/holoscan/input, output_path=/var/holoscan/output, model_path=/opt/holoscan/models, workdir=/var/holoscan), triton_server_netloc=\n",
      "\n",
      "[2025-04-22 17:27:53,860] [INFO] (root) - End compose\n",
      "\n",
      "[info] [gxf_executor.cpp:2396] Activating Graph...\n",
      "\n",
      "[info] [gxf_executor.cpp:2426] Running Graph...\n",
      "\n",
      "[info] [gxf_executor.cpp:2428] Waiting for completion...\n",
      "\n",
      "[info] [greedy_scheduler.cpp:191] Scheduling 6 entities\n",
      "\n",
      "[2025-04-22 17:27:53,886] [INFO] (monai.deploy.operators.dicom_data_loader_operator.DICOMDataLoaderOperator) - No or invalid input path from the optional input port: None\n",
      "\n",
      "[2025-04-22 17:27:54,799] [INFO] (root) - Finding series for Selection named: CT Series\n",
      "\n",
      "[2025-04-22 17:27:54,799] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291\n",
      "\n",
      "  # of series: 1\n",
      "\n",
      "[2025-04-22 17:27:54,799] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "\n",
      "[2025-04-22 17:27:54,799] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) -     Series attribute Modality value: CT\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series attribute string value did not match. Try regEx.\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series Selection finalized.\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series Description of selected DICOM Series for inference: ABD/PANC 3.0 B31f\n",
      "\n",
      "[2025-04-22 17:27:54,800] [INFO] (root) - Series Instance UID of selected DICOM Series for inference: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239\n",
      "\n",
      "[2025-04-22 17:27:55,081] [INFO] (root) - Casting to float32\n",
      "\n",
      "[2025-04-22 17:27:55,383] [INFO] (root) - Parsing from bundle_path: /opt/holoscan/models/model/model.ts\n",
      "\n",
      "/home/holoscan/.local/lib/python3.10/site-packages/monai/bundle/reference_resolver.py:216: UserWarning: Detected deprecated name 'optional_packages_version' in configuration file, replacing with 'required_packages_version'.\n",
      "\n",
      "  warnings.warn(\n",
      "\n",
      "[2025-04-22 17:27:59,716] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConversionOperator) - Output will be saved in file /var/holoscan/output/stl/spleen.stl.\n",
      "\n",
      "[2025-04-22 17:28:01,195] [INFO] (monai.deploy.operators.stl_conversion_operator.SpatialImage) - 3D image\n",
      "\n",
      "[2025-04-22 17:28:01,196] [INFO] (monai.deploy.operators.stl_conversion_operator.STLConverter) - Image ndarray shape:(204, 512, 512)\n",
      "\n",
      "/home/holoscan/.local/lib/python3.10/site-packages/highdicom/base.py:163: UserWarning: The string \"C3N-00198\" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in https://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.\n",
      "\n",
      "  check_person_name(patient_name)\n",
      "\n",
      "[2025-04-22 17:28:12,576] [INFO] (highdicom.base) - copy Image-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "\n",
      "[2025-04-22 17:28:12,576] [INFO] (highdicom.base) - copy attributes of module \"Specimen\"\n",
      "\n",
      "[2025-04-22 17:28:12,576] [INFO] (highdicom.base) - copy Patient-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "\n",
      "[2025-04-22 17:28:12,576] [INFO] (highdicom.base) - copy attributes of module \"Patient\"\n",
      "\n",
      "[2025-04-22 17:28:12,577] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Subject\"\n",
      "\n",
      "[2025-04-22 17:28:12,577] [INFO] (highdicom.base) - copy Study-related attributes from dataset \"1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191\"\n",
      "\n",
      "[2025-04-22 17:28:12,577] [INFO] (highdicom.base) - copy attributes of module \"General Study\"\n",
      "\n",
      "[2025-04-22 17:28:12,577] [INFO] (highdicom.base) - copy attributes of module \"Patient Study\"\n",
      "\n",
      "[2025-04-22 17:28:12,578] [INFO] (highdicom.base) - copy attributes of module \"Clinical Trial Study\"\n",
      "\n",
      "[info] [greedy_scheduler.cpp:372] Scheduler stopped: Some entities are waiting for execution, but there are no periodic or async entities to get out of the deadlock.\n",
      "\n",
      "[info] [greedy_scheduler.cpp:401] Scheduler finished.\n",
      "\n",
      "[info] [gxf_executor.cpp:2431] Deactivating Graph...\n",
      "\n",
      "[info] [gxf_executor.cpp:2439] Graph execution finished.\n",
      "\n",
      "[2025-04-22 17:28:12,698] [INFO] (app.AISpleenSegApp) - End run\n",
      "\n",
      "[2025-04-22 10:28:14,349] [INFO] (common) - Container 'youthful_jepsen'(21c6001bf0ef) exited.\n"
     ]
    }
   ],
   "source": [
    "# Clear the output folder and run the MAP. The input is expected to be a folder.\n",
    "!rm -rf $HOLOSCAN_OUTPUT_PATH\n",
    "!monai-deploy run -i $HOLOSCAN_INPUT_PATH -o $HOLOSCAN_OUTPUT_PATH my_app-x64-workstation-dgpu-linux-amd64:1.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.2.826.0.1.3680043.10.511.3.36310308785029269065941040056862019.dcm  stl\n"
     ]
    }
   ],
   "source": [
    "!ls $HOLOSCAN_OUTPUT_PATH"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
